Beispiel #1
0
    public function update_read_tracking($data)
    {
        // Mark the post and the topic read
        markread('post', (int) $data['forum_id'], (int) $data['topic_id'], $data['post_time']);
        markread('topic', (int) $data['forum_id'], (int) $data['topic_id'], time());
        // Handle read tracking
        if ($this->config['load_db_lastread'] && $this->user->data['is_registered']) {
            $sql = 'SELECT mark_time
				FROM ' . FORUMS_TRACK_TABLE . '
				WHERE user_id = ' . (int) $this->user->data['user_id'] . '
					AND forum_id = ' . (int) $data['forum_id'];
            $result = $this->db->sql_query($sql);
            $f_mark_time = (int) $this->db->sql_fetchfield('mark_time');
            $this->db->sql_freeresult($result);
        } else {
            if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) {
                $f_mark_time = false;
            }
        }
        if ($this->config['load_db_lastread'] && $this->user->data['is_registered'] || $this->config['load_anon_lastread'] || $this->user->data['is_registered']) {
            // Update forum info
            $sql = 'SELECT forum_last_post_time
				FROM ' . FORUMS_TABLE . '
				WHERE forum_id = ' . (int) $data['forum_id'];
            $result = $this->db->sql_query($sql);
            $forum_last_post_time = (int) $this->db->sql_fetchfield('forum_last_post_time');
            $this->db->sql_freeresult($result);
            update_forum_tracking_info((int) $data['forum_id'], $forum_last_post_time, $f_mark_time, false);
        }
    }
Beispiel #2
0
        $template->assign_block_vars('topicrow', $topic_row);
        $pagination->generate_template_pagination($view_topic_url, 'topicrow.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true);
        $s_type_switch = $row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL ? 1 : 0;
        /**
         * Event after the topic data has been assigned to the template
         *
         * @event core.viewforum_topic_row_after
         * @var	array	row				Array with the topic data
         * @var	array	rowset			Array with topics data (in topic_id => topic_data format)
         * @var	bool	s_type_switch	Flag indicating if the topic type is [global] announcement
         * @var	int		topic_id		The topic ID
         * @var	array	topic_list		Array with current viewforum page topic ids
         * @var	array	topic_row		Template array with topic data
         * @since 3.1.3-RC1
         */
        $vars = array('row', 'rowset', 's_type_switch', 'topic_id', 'topic_list', 'topic_row');
        extract($phpbb_dispatcher->trigger_event('core.viewforum_topic_row_after', compact($vars)));
        if ($unread_topic) {
            $mark_forum_read = false;
        }
        unset($rowset[$topic_id]);
    }
}
// This is rather a fudge but it's the best I can think of without requiring information
// on all topics (as we do in 2.0.x). It looks for unread or new topics, if it doesn't find
// any it updates the forum last read cookie. This requires that the user visit the forum
// after reading a topic
if ($forum_data['forum_type'] == FORUM_POST && sizeof($topic_list) && $mark_forum_read) {
    update_forum_tracking_info($forum_id, $forum_data['forum_last_post_time'], false, $mark_time_forum);
}
page_footer();
Beispiel #3
0
    $sql = 'UPDATE ' . TOPICS_TABLE . '
		SET topic_views = topic_views + 1, topic_last_view_time = ' . time() . "\n\t\tWHERE topic_id = {$topic_id}";
    $db->sql_query($sql);
    // Update the attachment download counts
    if (sizeof($update_count)) {
        $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
			SET download_count = download_count + 1
			WHERE ' . $db->sql_in_set('attach_id', array_unique($update_count));
        $db->sql_query($sql);
    }
}
// Only mark topic if it's currently unread. Also make sure we do not set topic tracking back if earlier pages are viewed.
if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id] && $max_post_time > $topic_tracking_info[$topic_id]) {
    markread('topic', $forum_id, $topic_id, $max_post_time);
    // Update forum info
    $all_marked_read = update_forum_tracking_info($forum_id, $topic_data['forum_last_post_time'], isset($topic_data['forum_mark_time']) ? $topic_data['forum_mark_time'] : false, false);
} else {
    $all_marked_read = true;
}
// If there are absolutely no more unread posts in this forum
// and unread posts shown, we can safely show the #unread link
if ($all_marked_read) {
    if ($post_unread) {
        $template->assign_vars(array('U_VIEW_UNREAD_POST' => '#unread'));
    } else {
        if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id]) {
            $template->assign_vars(array('U_VIEW_UNREAD_POST' => append_sid("{$phpbb_root_path}viewtopic.{$phpEx}", "f={$forum_id}&t={$topic_id}&view=unread") . '#unread'));
        }
    }
} else {
    if (!$all_marked_read) {
Beispiel #4
0
/**
* Handle topic bumping
* @param int $forum_id The ID of the forum the topic is being bumped belongs to
* @param int $topic_id The ID of the topic is being bumping
* @param array $post_data Passes some topic parameters:
*				- 'topic_title'
*				- 'topic_last_post_id'
*				- 'topic_last_poster_id'
*				- 'topic_last_post_subject'
*				- 'topic_last_poster_name'
*				- 'topic_last_poster_colour'
* @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time().
* @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&amptopic_id=2&ampp=3#p3
*/
function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false)
{
    global $config, $db, $user, $phpEx, $phpbb_root_path, $phpbb_log;
    if ($bump_time === false) {
        $bump_time = time();
    }
    // Begin bumping
    $db->sql_transaction('begin');
    // Update the topic's last post post_time
    $sql = 'UPDATE ' . POSTS_TABLE . "\n\t\tSET post_time = {$bump_time}\n\t\tWHERE post_id = {$post_data['topic_last_post_id']}\n\t\t\tAND topic_id = {$topic_id}";
    $db->sql_query($sql);
    // Sync the topic's last post time, the rest of the topic's last post data isn't changed
    $sql = 'UPDATE ' . TOPICS_TABLE . "\n\t\tSET topic_last_post_time = {$bump_time},\n\t\t\ttopic_bumped = 1,\n\t\t\ttopic_bumper = " . $user->data['user_id'] . "\n\t\tWHERE topic_id = {$topic_id}";
    $db->sql_query($sql);
    // Update the forum's last post info
    $sql = 'UPDATE ' . FORUMS_TABLE . "\n\t\tSET forum_last_post_id = " . $post_data['topic_last_post_id'] . ",\n\t\t\tforum_last_poster_id = " . $post_data['topic_last_poster_id'] . ",\n\t\t\tforum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "',\n\t\t\tforum_last_post_time = {$bump_time},\n\t\t\tforum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "',\n\t\t\tforum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "'\n\t\tWHERE forum_id = {$forum_id}";
    $db->sql_query($sql);
    // Update bumper's time of the last posting to prevent flood
    $sql = 'UPDATE ' . USERS_TABLE . "\n\t\tSET user_lastpost_time = {$bump_time}\n\t\tWHERE user_id = " . $user->data['user_id'];
    $db->sql_query($sql);
    $db->sql_transaction('commit');
    // Mark this topic as posted to
    markread('post', $forum_id, $topic_id, $bump_time);
    // Mark this topic as read
    markread('topic', $forum_id, $topic_id, $bump_time);
    // Update forum tracking info
    if ($config['load_db_lastread'] && $user->data['is_registered']) {
        $sql = 'SELECT mark_time
			FROM ' . FORUMS_TRACK_TABLE . '
			WHERE user_id = ' . $user->data['user_id'] . '
				AND forum_id = ' . $forum_id;
        $result = $db->sql_query($sql);
        $f_mark_time = (int) $db->sql_fetchfield('mark_time');
        $db->sql_freeresult($result);
    } else {
        if ($config['load_anon_lastread'] || $user->data['is_registered']) {
            $f_mark_time = false;
        }
    }
    if ($config['load_db_lastread'] && $user->data['is_registered'] || $config['load_anon_lastread'] || $user->data['is_registered']) {
        // Update forum info
        $sql = 'SELECT forum_last_post_time
			FROM ' . FORUMS_TABLE . '
			WHERE forum_id = ' . $forum_id;
        $result = $db->sql_query($sql);
        $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
        $db->sql_freeresult($result);
        update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false);
    }
    $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_BUMP_TOPIC', false, array('forum_id' => $forum_id, 'topic_id' => $topic_id, $post_data['topic_title']));
    $url = append_sid("{$phpbb_root_path}viewtopic.{$phpEx}", "f={$forum_id}&t={$topic_id}&p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}";
    return $url;
}
Beispiel #5
0
    $sql = $db->sql_build_query('SELECT', array('SELECT' => 'p.*, u.*, r.rank_title', 'FROM' => array(POSTS_TABLE => 'p', USERS_TABLE => 'u'), 'WHERE' => "p.topic_id = {$topic_id}\n\t\t\tAND p.post_id != {$report['post_id']}\n\t\t\t" . (!$auth->acl_get('m_approve', $forum_id) ? 'AND p.post_approved = 1' : '') . '
			AND u.user_id = p.poster_id', 'LEFT_JOIN' => array(array('FROM' => array(RANKS_TABLE => 'r'), 'ON' => 'u.user_rank = r.rank_id AND r.rank_special = 1')), 'ORDER_BY' => 'p.post_time ' . ($user->data['user_post_sortby_dir'] == 'a' ? 'ASC' : 'DESC')));
    $result = $db->sql_query($sql);
    $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_id);
    while ($row = $db->sql_fetchrow($result)) {
        $row['bbcode_options'] = ($row['enable_bbcode'] ? OPTION_FLAG_BBCODE : 0) + ($row['enable_smilies'] ? OPTION_FLAG_SMILIES : 0) + ($row['enable_magic_url'] ? OPTION_FLAG_LINKS : 0);
        $post_unread = isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id] ? true : false;
        // @todo add edit option?
        $template->assign_block_vars('commentrow', array('COMMENT_ID' => $row['post_id'], 'U_MINI_POST' => append_sid("{$phpbb_root_path}bugs.{$phpEx}", "mode=report&project={$report['project_name']}&report_id={$report_id}#comment-{$row['post_id']}"), 'POST_SUBJECT' => $row['post_subject'], 'POSTED_INFO' => sprintf($user->lang['POSTED_INFO'], get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $row['post_username']), $row['rank_title'] == '' ? '' : '(' . $row['rank_title'] . ')', $user->format_date($row['post_time'])), 'COMMENT_ID' => $row['post_id'], 'POST_AUTHOR' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $row['post_username']), 'MINI_POST_IMG' => $post_unread ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), 'MESSAGE' => generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']), 'COMMENT_ID' => $row['post_id'], 'COMMENT_ID' => $row['post_id'], 'U_MCP_REPORT' => $auth->acl_get('m_report', $forum_id) ? append_sid("{$phpbb_root_path}mcp.{$phpEx}", 'i=reports&mode=report_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'U_MCP_APPROVE' => $auth->acl_get('m_approve', $forum_id) ? append_sid("{$phpbb_root_path}mcp.{$phpEx}", 'i=queue&mode=approve_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'S_POST_REPORTED' => $row['post_reported'] == 1 && $auth->acl_get('m_report', $forum_id) ? true : false, 'S_POST_UNAPPROVED' => $row['post_approved'] == 0 ? true : false));
    }
    $db->sql_freeresult($result);
    // Mark comments read
    if (isset($topic_tracking_info[$topic_id]) && $report['topic_last_post_time'] > $topic_tracking_info[$topic_id] && $report['topic_last_post_time'] > $topic_tracking_info[$topic_id]) {
        markread('topic', $forum_id, $topic_id, $report['topic_last_post_time']);
        // Update forum info
        update_forum_tracking_info($forum_id, $report['forum_last_post_time']);
    }
    // Finally display the page
    site_header($user->lang['BUG_TRACKER'] . ' - ' . $report['report_title'], 'bugs', array(array('bugs.' . $phpEx, 'BUG_TRACKER'), array("bugs.{$phpEx}?mode=project&project={$report['project_name']}", $report['project_title']), array("bugs.{$phpEx}?mode=report&project={$report['project_name']}&report_id={$report_id}", sprintf($user->lang['BUG_NO'], $report_id))));
    $template->set_filenames(array('body' => 'bugs_report.html'));
    site_footer();
} elseif ($mode == 'add' || $mode == 'edit') {
    $project_name = request_var('project', '');
    $report_id = request_var('report_id', 0);
    // Load language file
    $user->add_lang('posting');
    // Include files
    include "{$phpbb_root_path}includes/functions_user.{$phpEx}";
    include "{$phpbb_root_path}includes/functions_posting.{$phpEx}";
    // Check if project exists (also grab project and forum data)
    $sql = $db->sql_build_query('SELECT', array('SELECT' => 'p.*, f.forum_status, f.enable_indexing', 'FROM' => array(BUGS_PROJECTS_TABLE => 'p'), 'LEFT_JOIN' => array(array('FROM' => array(FORUMS_TABLE => 'f'), 'ON' => 'p.forum_id = f.forum_id')), 'WHERE' => "p.project_name = '" . $db->sql_escape($project_name) . "'"));
Beispiel #6
0
	$sql = 'SELECT mark_time as forum_mark_time
		FROM ' . FORUMS_TRACK_TABLE . '
		WHERE forum_id = 0
			AND user_id = ' . $user->data['user_id'];
	$result = $db->sql_query($sql);
	$topic_data['forum_mark_time'] = (int) $db->sql_fetchfield('forum_mark_time');
	$db->sql_freeresult($result);
}

// Only mark topic if it's currently unread. Also make sure we do not set topic tracking back if earlier pages are viewed.
if (isset($topic_tracking_info[$topic_id]) && $topic_data['topic_last_post_time'] > $topic_tracking_info[$topic_id] && $max_post_time > $topic_tracking_info[$topic_id])
{
	markread('topic', (($topic_data['topic_type'] == POST_GLOBAL) ? 0 : $forum_id), $topic_id, $max_post_time);

	// Update forum info
	$all_marked_read = update_forum_tracking_info((($topic_data['topic_type'] == POST_GLOBAL) ? 0 : $forum_id), $topic_data['forum_last_post_time'], (isset($topic_data['forum_mark_time'])) ? $topic_data['forum_mark_time'] : false, false);
}
else
{
	$all_marked_read = true;
}

// If there are absolutely no more unread posts in this forum and unread posts shown, we can savely show the #unread link
if ($all_marked_read)
{
	if ($post_unread)
	{
		$template->assign_vars(array(
			'U_VIEW_UNREAD_POST'	=> '#unread',
		));
	}
/**
* Submit Post
* @todo Split up and create lightweight, simple API for this.
*/
function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
{
    global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path;
    // www.phpBB-SEO.com SEO TOOLKIT BEGIN
    global $phpbb_seo;
    // www.phpBB-SEO.com SEO TOOLKIT END
    // We do not handle erasing posts here
    if ($mode == 'delete') {
        return false;
    }
    $current_time = time();
    if ($mode == 'post') {
        $post_mode = 'post';
        $update_message = true;
    } else {
        if ($mode != 'edit') {
            $post_mode = 'reply';
            $update_message = true;
        } else {
            if ($mode == 'edit') {
                $post_mode = $data['topic_replies_real'] == 0 ? 'edit_topic' : ($data['topic_first_post_id'] == $data['post_id'] ? 'edit_first_post' : ($data['topic_last_post_id'] == $data['post_id'] ? 'edit_last_post' : 'edit'));
            }
        }
    }
    // First of all make sure the subject and topic title are having the correct length.
    // To achieve this without cutting off between special chars we convert to an array and then count the elements.
    $subject = truncate_string($subject);
    $data['topic_title'] = truncate_string($data['topic_title']);
    // Collect some basic information about which tables and which rows to update/insert
    $sql_data = $topic_row = array();
    $poster_id = $mode == 'edit' ? $data['poster_id'] : (int) $user->data['user_id'];
    // Retrieve some additional information if not present
    if ($mode == 'edit' && (!isset($data['post_approved']) || !isset($data['topic_approved']) || $data['post_approved'] === false || $data['topic_approved'] === false)) {
        $sql = 'SELECT p.post_approved, t.topic_type, t.topic_replies, t.topic_replies_real, t.topic_approved
			FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
			WHERE t.topic_id = p.topic_id
				AND p.post_id = ' . $data['post_id'];
        $result = $db->sql_query($sql);
        $topic_row = $db->sql_fetchrow($result);
        $db->sql_freeresult($result);
        $data['topic_approved'] = $topic_row['topic_approved'];
        $data['post_approved'] = $topic_row['post_approved'];
    }
    // This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval
    // The variable name should be $post_approved, because it indicates if the post is approved or not
    $post_approval = 1;
    // Check the permissions for post approval. Moderators are not affected.
    if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) {
        // Post not approved, but in queue
        $post_approval = 0;
    }
    // Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved
    if (isset($data['force_approved_state'])) {
        $post_approval = $data['force_approved_state'] ? 1 : 0;
    }
    // Start the transaction here
    $db->sql_transaction('begin');
    // Collect Information
    switch ($post_mode) {
        case 'post':
        case 'reply':
            $sql_data[POSTS_TABLE]['sql'] = array('forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'poster_id' => (int) $user->data['user_id'], 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_approved' => $post_approval, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => !$user->data['is_registered'] ? $username : '', 'post_subject' => $subject, 'post_text' => $data['message'], 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_postcount' => $auth->acl_get('f_postcount', $data['forum_id']) ? 1 : 0, 'post_edit_locked' => $data['post_edit_locked']);
            break;
        case 'edit_first_post':
        case 'edit':
        case 'edit_last_post':
        case 'edit_topic':
            // If edit reason is given always display edit info
            // If editing last post then display no edit info
            // If m_edit permission then display no edit info
            // If normal edit display edit info
            // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
            if ($data['post_edit_reason'] || !$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')) {
                $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
                $sql_data[POSTS_TABLE]['sql'] = array('post_edit_time' => $current_time, 'post_edit_reason' => $data['post_edit_reason'], 'post_edit_user' => (int) $data['post_edit_user']);
                $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
            } else {
                if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id'])) {
                    $sql_data[POSTS_TABLE]['sql'] = array('post_edit_reason' => '');
                }
            }
            // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
            // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
            if ($user->data['user_id'] != $poster_id) {
                $log_subject = $subject ? $subject : $data['topic_title'];
                add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, !empty($username) ? $username : $user->lang['GUEST']);
            }
            if (!isset($sql_data[POSTS_TABLE]['sql'])) {
                $sql_data[POSTS_TABLE]['sql'] = array();
            }
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], 'post_approved' => !$post_approval ? 0 : $data['post_approved'], 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => $username && $data['poster_id'] == ANONYMOUS ? $username : '', 'post_subject' => $subject, 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_edit_locked' => $data['post_edit_locked']));
            if ($update_message) {
                $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
            }
            break;
    }
    $post_approved = $sql_data[POSTS_TABLE]['sql']['post_approved'];
    $topic_row = array();
    // And the topic ladies and gentlemen
    switch ($post_mode) {
        case 'post':
            $sql_data[TOPICS_TABLE]['sql'] = array('topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, 'forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => $post_approval, 'topic_title' => $subject, 'topic_first_poster_name' => !$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : 0);
            // www.phpBB-SEO.com SEO TOOLKIT BEGIN
            if (!empty($phpbb_seo->seo_opt['sql_rewrite'])) {
                $sql_data[TOPICS_TABLE]['sql'] += array('topic_url' => isset($data['topic_url']) ? $data['topic_url'] : '');
            }
            // www.phpBB-SEO.com SEO TOOLKIT END
            if (isset($poll['poll_options']) && !empty($poll['poll_options'])) {
                $poll_start = $poll['poll_start'] ? $poll['poll_start'] : $current_time;
                $poll_length = $poll['poll_length'] * 86400;
                if ($poll_length < 0) {
                    $poll_start = $poll_start + $poll_length;
                    if ($poll_start < 0) {
                        $poll_start = 0;
                    }
                    $poll_length = 1;
                }
                $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array('poll_title' => $poll['poll_title'], 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']));
            }
            $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval ? ', user_posts = user_posts + 1' : '');
            if ($topic_type != POST_GLOBAL) {
                if ($post_approval) {
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1';
                }
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . ($post_approval ? ', forum_topics = forum_topics + 1' : '');
            }
            break;
        case 'reply':
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
				topic_replies_real = topic_replies_real + 1,
				topic_bumped = 0,
				topic_bumper = 0' . ($post_approval ? ', topic_replies = topic_replies + 1' : '') . (!empty($data['attachment_data']) || isset($data['topic_attachment']) && $data['topic_attachment'] ? ', topic_attachment = 1' : '');
            $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval ? ', user_posts = user_posts + 1' : '');
            if ($post_approval && $topic_type != POST_GLOBAL) {
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1';
            }
            break;
        case 'edit_topic':
        case 'edit_first_post':
            if (isset($poll['poll_options']) && !empty($poll['poll_options'])) {
                $poll_start = $poll['poll_start'] ? $poll['poll_start'] : $current_time;
                $poll_length = $poll['poll_length'] * 86400;
                if ($poll_length < 0) {
                    $poll_start = $poll_start + $poll_length;
                    if ($poll_start < 0) {
                        $poll_start = 0;
                    }
                    $poll_length = 1;
                }
            }
            $sql_data[TOPICS_TABLE]['sql'] = array('forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => !$post_approval ? 0 : $data['topic_approved'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'poll_title' => isset($poll['poll_options']) ? $poll['poll_title'] : '', 'poll_start' => isset($poll['poll_options']) ? $poll_start : 0, 'poll_max_options' => isset($poll['poll_options']) ? $poll['poll_max_options'] : 1, 'poll_length' => isset($poll['poll_options']) ? $poll_length : 0, 'poll_vote_change' => isset($poll['poll_vote_change']) ? $poll['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0));
            // www.phpBB-SEO.com SEO TOOLKIT BEGIN
            if (!empty($phpbb_seo->seo_opt['sql_rewrite'])) {
                $sql_data[TOPICS_TABLE]['sql'] += array('topic_url' => isset($data['topic_url']) ? $data['topic_url'] : '');
            }
            // www.phpBB-SEO.com SEO TOOLKIT END
            // Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved
            if (!$post_approval && $data['topic_approved']) {
                // Do we need to grab some topic informations?
                if (!sizeof($topic_row)) {
                    $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved
						FROM ' . TOPICS_TABLE . '
						WHERE topic_id = ' . $data['topic_id'];
                    $result = $db->sql_query($sql);
                    $topic_row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                }
                // If this is the only post remaining we do not need to decrement topic_replies.
                // Also do not decrement if first post - then the topic_replies will not be adjusted if approving the topic again.
                // If this is an edited topic or the first post the topic gets completely disapproved later on...
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1';
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1);
                set_config_count('num_topics', -1, true);
                set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * -1, true);
                // Only decrement this post, since this is the one non-approved now
                if ($auth->acl_get('f_postcount', $data['forum_id'])) {
                    $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1';
                }
            }
            break;
        case 'edit':
        case 'edit_last_post':
            // Correctly set back the topic replies and forum posts... but only if the post was approved before.
            if (!$post_approval && $data['post_approved']) {
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time;
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1';
                set_config_count('num_posts', -1, true);
                if ($auth->acl_get('f_postcount', $data['forum_id'])) {
                    $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1';
                }
            }
            break;
    }
    // Submit new topic
    if ($post_mode == 'post') {
        $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
        $db->sql_query($sql);
        $data['topic_id'] = $db->sql_nextid();
        $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
        unset($sql_data[TOPICS_TABLE]['sql']);
    }
    // Submit new post
    if ($post_mode == 'post' || $post_mode == 'reply') {
        if ($post_mode == 'reply') {
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
        }
        $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
        $db->sql_query($sql);
        $data['post_id'] = $db->sql_nextid();
        if ($post_mode == 'post') {
            $sql_data[TOPICS_TABLE]['sql'] = array('topic_first_post_id' => $data['post_id'], 'topic_last_post_id' => $data['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => (int) $user->data['user_id'], 'topic_last_poster_name' => !$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : ''), 'topic_last_poster_colour' => $user->data['user_colour'], 'topic_last_post_subject' => (string) $subject);
        }
        unset($sql_data[POSTS_TABLE]['sql']);
    }
    $make_global = false;
    // Are we globalising or unglobalising?
    if ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic') {
        if (!sizeof($topic_row)) {
            $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved, topic_last_post_id
				FROM ' . TOPICS_TABLE . '
				WHERE topic_id = ' . $data['topic_id'];
            $result = $db->sql_query($sql);
            $topic_row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
        }
        // globalise/unglobalise?
        if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL || $topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL) {
            if (!empty($sql_data[FORUMS_TABLE]['stat']) && implode('', $sql_data[FORUMS_TABLE]['stat'])) {
                $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET ' . implode(', ', $sql_data[FORUMS_TABLE]['stat']) . ' WHERE forum_id = ' . $data['forum_id']);
            }
            $make_global = true;
            $sql_data[FORUMS_TABLE]['stat'] = array();
        }
        // globalise
        if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL) {
            // Decrement topic/post count
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies_real'] + 1);
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real - 1' . ($topic_row['topic_approved'] ? ', forum_topics = forum_topics - 1' : '');
            // Update forum_ids for all posts
            $sql = 'UPDATE ' . POSTS_TABLE . '
				SET forum_id = 0
				WHERE topic_id = ' . $data['topic_id'];
            $db->sql_query($sql);
        } else {
            if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL) {
                // Increment topic/post count
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + ' . ($topic_row['topic_replies_real'] + 1);
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . ($topic_row['topic_approved'] ? ', forum_topics = forum_topics + 1' : '');
                // Update forum_ids for all posts
                $sql = 'UPDATE ' . POSTS_TABLE . '
				SET forum_id = ' . $data['forum_id'] . '
				WHERE topic_id = ' . $data['topic_id'];
                $db->sql_query($sql);
            }
        }
    }
    // Update the topics table
    if (isset($sql_data[TOPICS_TABLE]['sql'])) {
        $sql = 'UPDATE ' . TOPICS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
			WHERE topic_id = ' . $data['topic_id'];
        $db->sql_query($sql);
    }
    // Update the posts table
    if (isset($sql_data[POSTS_TABLE]['sql'])) {
        $sql = 'UPDATE ' . POSTS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
			WHERE post_id = ' . $data['post_id'];
        $db->sql_query($sql);
    }
    // Update Poll Tables
    if (isset($poll['poll_options']) && !empty($poll['poll_options'])) {
        $cur_poll_options = array();
        if ($poll['poll_start'] && $mode == 'edit') {
            $sql = 'SELECT *
				FROM ' . POLL_OPTIONS_TABLE . '
				WHERE topic_id = ' . $data['topic_id'] . '
				ORDER BY poll_option_id';
            $result = $db->sql_query($sql);
            $cur_poll_options = array();
            while ($row = $db->sql_fetchrow($result)) {
                $cur_poll_options[] = $row;
            }
            $db->sql_freeresult($result);
        }
        $sql_insert_ary = array();
        for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) {
            if (strlen(trim($poll['poll_options'][$i]))) {
                if (empty($cur_poll_options[$i])) {
                    // If we add options we need to put them to the end to be able to preserve votes...
                    $sql_insert_ary[] = array('poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), 'topic_id' => (int) $data['topic_id'], 'poll_option_text' => (string) $poll['poll_options'][$i]);
                } else {
                    if ($poll['poll_options'][$i] != $cur_poll_options[$i]) {
                        $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "\n\t\t\t\t\t\tSET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'\n\t\t\t\t\t\tWHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
							AND topic_id = ' . $data['topic_id'];
                        $db->sql_query($sql);
                    }
                }
            }
        }
        $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
        if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) {
            $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
				WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
					AND topic_id = ' . $data['topic_id'];
            $db->sql_query($sql);
        }
        // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
        if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) {
            $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
            $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
        }
    }
    // Submit Attachments
    if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) {
        $space_taken = $files_added = 0;
        $orphan_rows = array();
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            $orphan_rows[(int) $attach_row['attach_id']] = array();
        }
        if (sizeof($orphan_rows)) {
            $sql = 'SELECT attach_id, filesize, physical_filename
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
					AND is_orphan = 1
					AND poster_id = ' . $user->data['user_id'];
            $result = $db->sql_query($sql);
            $orphan_rows = array();
            while ($row = $db->sql_fetchrow($result)) {
                $orphan_rows[$row['attach_id']] = $row;
            }
            $db->sql_freeresult($result);
        }
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) {
                continue;
            }
            if (!$attach_row['is_orphan']) {
                // update entry in db if attachment already stored in db and filespace
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "\n\t\t\t\t\tSET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'\n\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'] . '
						AND is_orphan = 0';
                $db->sql_query($sql);
            } else {
                // insert attachment into db
                if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) {
                    continue;
                }
                $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
                $files_added++;
                $attach_sql = array('post_msg_id' => $data['post_id'], 'topic_id' => $data['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment']);
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
					WHERE attach_id = ' . $attach_row['attach_id'] . '
						AND is_orphan = 1
						AND poster_id = ' . $user->data['user_id'];
                $db->sql_query($sql);
            }
        }
        if ($space_taken && $files_added) {
            set_config_count('upload_dir_size', $space_taken, true);
            set_config_count('num_files', $files_added, true);
        }
    }
    // we need to update the last forum information
    // only applicable if the topic is not global and it is approved
    // we also check to make sure we are not dealing with globaling the latest topic (pretty rare but still needs to be checked)
    if ($topic_type != POST_GLOBAL && !$make_global && ($post_approved || !$data['post_approved'])) {
        // the last post makes us update the forum table. This can happen if...
        // We make a new topic
        // We reply to a topic
        // We edit the last post in a topic and this post is the latest in the forum (maybe)
        // We edit the only post in the topic
        // We edit the first post in the topic and all the other posts are not approved
        if (($post_mode == 'post' || $post_mode == 'reply') && $post_approved) {
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(!$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : '')) . "'";
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
        } else {
            if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $post_mode == 'edit_first_post' && !$data['topic_replies']) {
                // this does not _necessarily_ mean that we must update the info again,
                // it just means that we might have to
                $sql = 'SELECT forum_last_post_id, forum_last_post_subject
				FROM ' . FORUMS_TABLE . '
				WHERE forum_id = ' . (int) $data['forum_id'];
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                // this post is the latest post in the forum, better update
                if ($row['forum_last_post_id'] == $data['post_id']) {
                    // If post approved and subject changed, or poster is anonymous, we need to update the forum_last* rows
                    if ($post_approved && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) {
                        // the post's subject changed
                        if ($row['forum_last_post_subject'] !== $subject) {
                            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_subject = \'' . $db->sql_escape($subject) . '\'';
                        }
                        // Update the user name if poster is anonymous... just in case an admin changed it
                        if ($data['poster_id'] == ANONYMOUS) {
                            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
                        }
                    } else {
                        if ($data['post_approved'] !== $post_approved) {
                            // we need a fresh change of socks, everything has become invalidated
                            $sql = 'SELECT MAX(topic_last_post_id) as last_post_id
						FROM ' . TOPICS_TABLE . '
						WHERE forum_id = ' . (int) $data['forum_id'] . '
							AND topic_approved = 1';
                            $result = $db->sql_query($sql);
                            $row = $db->sql_fetchrow($result);
                            $db->sql_freeresult($result);
                            // any posts left in this forum?
                            if (!empty($row['last_post_id'])) {
                                $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
							FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
							WHERE p.poster_id = u.user_id
								AND p.post_id = ' . (int) $row['last_post_id'];
                                $result = $db->sql_query($sql);
                                $row = $db->sql_fetchrow($result);
                                $db->sql_freeresult($result);
                                // salvation, a post is found! jam it into the forums table
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
                            } else {
                                // just our luck, the last topic in the forum has just been turned unapproved...
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0';
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''";
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0';
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0';
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''";
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''";
                            }
                        }
                    }
                }
            }
        }
    } else {
        if ($make_global) {
            // somebody decided to be a party pooper, we must recalculate the whole shebang (maybe)
            $sql = 'SELECT forum_last_post_id
			FROM ' . FORUMS_TABLE . '
			WHERE forum_id = ' . (int) $data['forum_id'];
            $result = $db->sql_query($sql);
            $forum_row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            // we made a topic global, go get new data
            if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL && $forum_row['forum_last_post_id'] == $topic_row['topic_last_post_id']) {
                // we need a fresh change of socks, everything has become invalidated
                $sql = 'SELECT MAX(topic_last_post_id) as last_post_id
				FROM ' . TOPICS_TABLE . '
				WHERE forum_id = ' . (int) $data['forum_id'] . '
					AND topic_approved = 1';
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                // any posts left in this forum?
                if (!empty($row['last_post_id'])) {
                    $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
					FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
					WHERE p.poster_id = u.user_id
						AND p.post_id = ' . (int) $row['last_post_id'];
                    $result = $db->sql_query($sql);
                    $row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                    // salvation, a post is found! jam it into the forums table
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
                } else {
                    // just our luck, the last topic in the forum has just been globalized...
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0';
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''";
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0';
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0';
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''";
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''";
                }
            } else {
                if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL && $forum_row['forum_last_post_id'] < $topic_row['topic_last_post_id']) {
                    // this post has a higher id, it is newer
                    $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
				WHERE p.poster_id = u.user_id
					AND p.post_id = ' . (int) $topic_row['topic_last_post_id'];
                    $result = $db->sql_query($sql);
                    $row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                    // salvation, a post is found! jam it into the forums table
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
                }
            }
        }
    }
    // topic sync time!
    // simply, we update if it is a reply or the last post is edited
    if ($post_approved) {
        // reply requires the whole thing
        if ($post_mode == 'reply') {
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $data['post_id'];
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $user->data['user_id'];
            $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape(!$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : '')) . "'";
            $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . ($user->data['user_id'] != ANONYMOUS ? $db->sql_escape($user->data['user_colour']) : '') . "'";
            $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $current_time;
        } else {
            if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $post_mode == 'edit_first_post' && !$data['topic_replies']) {
                // only the subject can be changed from edit
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
                // Maybe not only the subject, but also changing anonymous usernames. ;)
                if ($data['poster_id'] == ANONYMOUS) {
                    $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
                }
            }
        }
    } else {
        if (!$data['post_approved'] && ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $post_mode == 'edit_first_post' && !$data['topic_replies'])) {
            // like having the rug pulled from under us
            $sql = 'SELECT MAX(post_id) as last_post_id
			FROM ' . POSTS_TABLE . '
			WHERE topic_id = ' . (int) $data['topic_id'] . '
				AND post_approved = 1';
            $result = $db->sql_query($sql);
            $row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            // any posts left in this forum?
            if (!empty($row['last_post_id'])) {
                $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
				WHERE p.poster_id = u.user_id
					AND p.post_id = ' . (int) $row['last_post_id'];
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                // salvation, a post is found! jam it into the topics table
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $row['post_id'];
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $row['post_time'];
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $row['poster_id'];
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
            }
        }
    }
    // Update total post count, do not consider moderated posts/topics
    if ($post_approval) {
        if ($post_mode == 'post') {
            set_config_count('num_topics', 1, true);
            set_config_count('num_posts', 1, true);
        }
        if ($post_mode == 'reply') {
            set_config_count('num_posts', 1, true);
        }
    }
    // Update forum stats
    $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id);
    foreach ($sql_data as $table => $update_ary) {
        if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) {
            $sql = "UPDATE {$table} SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
            $db->sql_query($sql);
        }
    }
    // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
    if ($make_global) {
        $sql = 'DELETE FROM ' . TOPICS_TABLE . '
			WHERE topic_moved_id = ' . $data['topic_id'];
        $db->sql_query($sql);
    }
    // Committing the transaction before updating search index
    $db->sql_transaction('commit');
    // Delete draft if post was loaded...
    $draft_id = request_var('draft_loaded', 0);
    if ($draft_id) {
        $sql = 'DELETE FROM ' . DRAFTS_TABLE . "\n\t\t\tWHERE draft_id = {$draft_id}\n\t\t\t\tAND user_id = {$user->data['user_id']}";
        $db->sql_query($sql);
    }
    // Index message contents
    if ($update_search_index && $data['enable_indexing']) {
        // Select the search method and do some additional checks to ensure it can actually be utilised
        $search_type = basename($config['search_type']);
        if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) {
            trigger_error('NO_SUCH_SEARCH_MODULE');
        }
        if (!class_exists($search_type)) {
            include "{$phpbb_root_path}includes/search/{$search_type}.{$phpEx}";
        }
        $error = false;
        $search = new $search_type($error);
        if ($error) {
            trigger_error($error);
        }
        $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $topic_type == POST_GLOBAL ? 0 : $data['forum_id']);
    }
    // Topic Notification, do not change if moderator is changing other users posts...
    if ($user->data['user_id'] == $poster_id) {
        if (!$data['notify_set'] && $data['notify']) {
            $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
				VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
            $db->sql_query($sql);
        } else {
            if ($data['notify_set'] && !$data['notify']) {
                $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
				WHERE user_id = ' . $user->data['user_id'] . '
					AND topic_id = ' . $data['topic_id'];
                $db->sql_query($sql);
            }
        }
    }
    if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') {
        // Mark this topic as posted to
        markread('post', $data['forum_id'], $data['topic_id'], $data['post_time']);
    }
    // Mark this topic as read
    // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
    markread('topic', $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], $data['topic_id'], time());
    //
    if ($config['load_db_lastread'] && $user->data['is_registered']) {
        $sql = 'SELECT mark_time
			FROM ' . FORUMS_TRACK_TABLE . '
			WHERE user_id = ' . $user->data['user_id'] . '
				AND forum_id = ' . ($topic_type == POST_GLOBAL ? 0 : $data['forum_id']);
        $result = $db->sql_query($sql);
        $f_mark_time = (int) $db->sql_fetchfield('mark_time');
        $db->sql_freeresult($result);
    } else {
        if ($config['load_anon_lastread'] || $user->data['is_registered']) {
            $f_mark_time = false;
        }
    }
    if ($config['load_db_lastread'] && $user->data['is_registered'] || $config['load_anon_lastread'] || $user->data['is_registered']) {
        // Update forum info
        if ($topic_type == POST_GLOBAL) {
            $sql = 'SELECT MAX(topic_last_post_time) as forum_last_post_time
				FROM ' . TOPICS_TABLE . '
				WHERE forum_id = 0';
        } else {
            $sql = 'SELECT forum_last_post_time
				FROM ' . FORUMS_TABLE . '
				WHERE forum_id = ' . $data['forum_id'];
        }
        $result = $db->sql_query($sql);
        $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
        $db->sql_freeresult($result);
        update_forum_tracking_info($topic_type == POST_GLOBAL ? 0 : $data['forum_id'], $forum_last_post_time, $f_mark_time, false);
    }
    // Send Notifications
    if ($mode != 'edit' && $mode != 'delete' && $post_approval) {
        user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']);
    }
    $params = $add_anchor = '';
    if ($post_approval) {
        $params .= '&amp;t=' . $data['topic_id'];
        if ($mode != 'post') {
            $params .= '&amp;p=' . $data['post_id'];
            $add_anchor = '#p' . $data['post_id'];
        }
    } else {
        if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') {
            $params .= '&amp;t=' . $data['topic_id'];
        }
    }
    // www.phpBB-SEO.com SEO TOOLKIT BEGIN
    $phpbb_seo->set_url($data['forum_name'], $data['forum_id'], $phpbb_seo->seo_static['forum']);
    if ($params) {
        $phpbb_seo->prepare_iurl($data, 'topic', $topic_type == POST_GLOBAL ? $phpbb_seo->seo_static['global_announce'] : $phpbb_seo->seo_url['forum'][$data['forum_id']]);
    }
    // www.phpBB-SEO.com SEO TOOLKIT END
    $url = !$params ? "{$phpbb_root_path}viewforum.{$phpEx}" : "{$phpbb_root_path}viewtopic.{$phpEx}";
    $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
    return $url;
}
    function _submit(&$sync)
    {
        global $config, $db, $auth, $user;
        if ($sync === false) {
            //submit() was called directly so we need to sync after it
            $sync = new syncer();
            $exec_sync = true;
        } else {
            //submit() was called by topic->submit(), sync there when everything is done
            $exec_sync = false;
        }
        if (!$this->post_id) {
            //new post, set some default values if not set yet
            if (!$this->poster_id) {
                $this->poster_id = $user->data['user_id'];
            }
            if (!$this->poster_ip) {
                $this->poster_ip = $user->ip;
            }
            if (!$this->post_time) {
                $this->post_time = time();
            }
        }
        $this->post_subject = truncate_string($this->post_subject);
        $sql_data = array('poster_id' => $this->poster_id, 'poster_ip' => $this->poster_ip, 'topic_id' => $this->topic_id, 'forum_id' => $this->forum_id, 'post_username' => $this->post_username, 'icon_id' => $this->icon_id, 'post_time' => $this->post_time, 'post_postcount' => $this->post_postcount ? 1 : 0, 'post_visibility' => $this->post_visibility, 'post_reported' => $this->post_reported ? 1 : 0, 'enable_bbcode' => $this->enable_bbcode ? 1 : 0, 'enable_smilies' => $this->enable_smilies ? 1 : 0, 'enable_magic_url' => $this->enable_magic_url ? 1 : 0, 'enable_sig' => $this->enable_sig ? 1 : 0, 'post_subject' => $this->post_subject, 'bbcode_bitfield' => 0, 'bbcode_uid' => '', 'post_text' => $this->post_text, 'post_checksum' => md5($this->post_text), 'post_edit_time' => $this->post_edit_time, 'post_edit_reason' => $this->post_edit_reason, 'post_edit_user' => $this->post_edit_user, 'post_edit_count' => $this->post_edit_count, 'post_edit_locked' => $this->post_edit_locked, 'post_delete_time' => $this->post_delete_time, 'post_delete_reason' => $this->post_delete_reason, 'post_delete_user' => $this->post_delete_user);
        $flags = '';
        generate_text_for_storage($sql_data['post_text'], $sql_data['bbcode_uid'], $sql_data['bbcode_bitfield'], $flags, $this->enable_bbcode, $this->enable_magic_url, $this->enable_smilies);
        if ($this->post_id && $this->topic_id) {
            //edit
            $sql = "SELECT p.*, t.topic_first_post_id, t.topic_last_post_id, t.topic_approved, t.topic_replies\n\t\t\t\t\tFROM " . POSTS_TABLE . " p\n\t\t\t\t\tLEFT JOIN " . TOPICS_TABLE . " t ON (t.topic_id = p.topic_id)\n\t\t\t\t\tWHERE p.post_id=" . intval($this->post_id);
            //$sql = "SELECT * FROM " . POSTS_TABLE . " WHERE post_id=" . intval($this->post_id);
            $result = $db->sql_query($sql);
            $post_data = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            if (!$post_data) {
                trigger_error("post_id={$this->post_id}, but that post does not exist", E_USER_ERROR);
            }
            //check first/last post
            $is_first_post = $post_data['post_id'] == $post_data['topic_first_post_id'];
            $is_last_post = $post_data['post_id'] == $post_data['topic_last_post_id'];
            $db->sql_transaction('begin');
            $sql = "UPDATE " . POSTS_TABLE . " SET " . $db->sql_build_array('UPDATE', $sql_data) . " WHERE post_id=" . $this->post_id;
            $db->sql_query($sql);
            if ($this->topic_id != $post_data['topic_id']) {
                //merge into new topic
                //get new topic's forum id and first/last post time
                $sql = "SELECT forum_id, topic_time, topic_last_post_time\n\t\t\t\t\t\tFROM " . TOPICS_TABLE . "\n\t\t\t\t\t\tWHERE topic_id = {$this->topic_id}";
                $result = $db->sql_query($sql);
                $new_topic_data = $db->sql_fetchrow($result);
                if (!$new_topic_data) {
                    trigger_error("attempted to merge post {$this->post_id} into topic {$this->topic_id}, but that topic does not exist", E_USER_ERROR);
                }
                //sync forum_posts
                //TODO
                if ($new_topic_data['forum_id'] != $post_data['forum_id']) {
                    $sync->add('forum', $post_data['forum_id'], 'forum_posts', $this->post_approved ? -1 : 0);
                    $sync->add('forum', $new_topic_data['forum_id'], 'forum_posts', $this->post_approved ? 1 : 0);
                    if ($this->forum_id != $new_topic_data['forum_id']) {
                        //user changed topic_id but not forum_id, so we saved the wrong one above. correct it via sync
                        $this->forum_id = $new_topic_data['forum_id'];
                        $sync->set('post', $this->post_id, 'forum_id', $this->forum_id);
                    }
                }
                //sync old topic
                $sync->add('topic', $post_data['topic_id'], 'topic_replies', $this->post_approved ? -1 : 0);
                $sync->add('topic', $post_data['topic_id'], 'topic_replies_real', -1);
                $sync->check_topic_empty($post_data['topic_id']);
                //sync new topic
                $sync->add('topic', $this->topic_id, 'topic_replies', $this->post_approved ? 1 : 0);
                $sync->add('topic', $this->topic_id, 'topic_replies_real', 1);
                //sync topic_reported and topic_attachment if applicable
                if ($post_data['post_reported']) {
                    $sync->topic_reported($post_data['topic_id']);
                }
                if ($post_data['post_attachment']) {
                    $sync->topic_attachment($post_data['topic_id']);
                }
                if ($this->post_reported) {
                    $sync->topic_reported($this->topic_id);
                }
                if ($this->post_attachment) {
                    $sync->topic_attachment($this->topic_id);
                }
                if ($is_first_post) {
                    //this was the first post in the old topic, sync it
                    $sync->topic_first_post($post_data['topic_id']);
                    $is_first_post = false;
                    //unset since we dont know status for new topic yet
                }
                if ($is_last_post) {
                    //this was the last post in the old topic, sync it
                    $sync->topic_last_post($post_data['topic_id']);
                    $sync->forum_last_post($post_data['forum_id']);
                    $is_last_post = false;
                    //unset since we dont know status for new topic yet
                }
                if ($this->post_time <= $new_topic_data['topic_time']) {
                    //this will be the first post in the new topic, sync it
                    $sync->topic_first_post($this->topic_id);
                    $is_first_post = true;
                }
                if ($this->post_time >= $new_topic_data['topic_last_post_time']) {
                    //this will be the last post in the new topic, sync it
                    $sync->topic_last_post($this->topic_id);
                    $sync->forum_last_post($this->topic_id);
                    $is_last_post = true;
                }
            } elseif ($is_first_post) {
                $sync->set('topic', $this->topic_id, array('icon_id' => $this->icon_id, 'topic_approved' => $this->post_approved, 'topic_title' => $this->post_subject, 'topic_poster' => $this->poster_id, 'topic_time' => $this->post_time));
            }
            //check if some statistics relevant flags have been changed
            if ($this->post_approved != $post_data['post_approved']) {
                //if topic_id was changed, we've already updated it above.
                if ($this->topic_id == $post_data['topic_id']) {
                    if ($is_first_post) {
                        //first post -> approve/disapprove whole topic if not yet done (should only happen when directly storing the post)
                        if ($this->post_approved != $post_data['topic_approved']) {
                            $sync->add('forum', $this->forum_id, 'forum_topics', $this->post_approved ? 1 : -1);
                            $sync->add('forum', $this->forum_id, 'forum_posts', $this->post_approved ? 1 + $post_data['topic_replies'] : -(1 + $post_data['topic_replies']));
                            $sync->forum_last_post($this->forum_id);
                            //and the total topics+posts
                            set_config('num_topics', $this->post_approved ? $config['num_topics'] + 1 : $config['num_topics'] - 1, true);
                            set_config('num_posts', $this->post_approved ? $config['num_posts'] + (1 + $post_data['topic_replies']) : $config['num_posts'] - (1 + $post_data['topic_replies']), true);
                        }
                    } else {
                        //reply
                        $sync->add('topic', $this->topic_id, 'topic_replies', $this->post_approved ? 1 : -1);
                        $sync->add('forum', $this->forum_id, 'forum_posts', $this->post_approved ? 1 : -1);
                    }
                }
                //update total posts
                if (!$is_first_post) {
                    set_config('num_posts', $this->post_approved ? $config['num_posts'] + 1 : $config['num_posts'] - 1, true);
                }
            }
            /*if($this->post_postcount != $post_data['post_postcount'] && $this->poster_id != ANONYMOUS)
            		{
            			//increase or decrease user_posts
            			$sync->add('user', $this->poster_id, 'user_posts', $this->post_approved ? 1 : -1);
            		}*/
            if ($this->poster_id != $post_data['poster_id'] || $this->post_postcount != $post_data['post_postcount']) {
                if ($post_data['post_postcount'] && $post_data['poster_id'] != ANONYMOUS) {
                    $sync->add('user', $post_data['poster_id'], 'user_posts', -1);
                }
                if ($this->post_postcount && $this->poster_id != ANONYMOUS) {
                    $sync->add('user', $this->poster_id, 'user_posts', 1);
                }
            }
            if ($is_first_post) {
                $sync->topic_first_post($this->topic_id);
            }
            if ($is_last_post) {
                $sync->topic_last_post($this->topic_id);
                $sync->forum_last_post($this->forum_id);
            }
            reindex('edit', $this->post_id, $sql_data['post_text'], $this->post_subject, $this->poster_id, $this->forum_id);
            $db->sql_transaction('commit');
        } elseif ($this->topic_id) {
            //reply
            $sql = "SELECT t.*, f.forum_name\n\t\t\t\t\tFROM " . TOPICS_TABLE . " t\n\t\t\t\t\tLEFT JOIN " . FORUMS_TABLE . " f ON (f.forum_id = t.forum_id)\n\t\t\t\t\tWHERE t.topic_id=" . intval($this->topic_id);
            $result = $db->sql_query($sql);
            $topic_data = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            if (!$topic_data) {
                trigger_error("topic_id={$this->topic_id}, but that topic does not exist", E_USER_ERROR);
            }
            //we need topic_id and forum_id
            $this->forum_id = $topic_data['forum_id'];
            $sql_data['forum_id'] = $this->forum_id;
            $sql_data['topic_id'] = $this->topic_id;
            //make sure we have a post_subject (empty subjects are bad for e.g. approving)
            if ($this->post_subject == '') {
                $this->post_subject = 'Re: ' . $topic_data['topic_title'];
            }
            $db->sql_transaction('begin');
            //insert post
            $sql = "INSERT INTO " . POSTS_TABLE . " " . $db->sql_build_array('INSERT', $sql_data);
            $db->sql_query($sql);
            $this->post_id = $db->sql_nextid();
            //update topic
            if (!$sync->new_topic_flag) {
                $sync->add('topic', $this->topic_id, 'topic_replies', $this->post_approved ? 1 : 0);
                $sync->add('topic', $this->topic_id, 'topic_replies_real', 1);
                $sync->set('topic', $this->topic_id, 'topic_bumped', 0);
                $sync->set('topic', $this->topic_id, 'topic_bumper', 0);
            } else {
                $sync->topic_first_post($this->topic_id);
                $sync->new_topic_flag = false;
            }
            $sync->topic_last_post($this->topic_id);
            //update forum
            if ($this->forum_id != 0) {
                $sync->add('forum', $this->forum_id, 'forum_posts', $this->post_approved ? 1 : 0);
                $sync->forum_last_post($this->forum_id);
            }
            if ($this->post_postcount) {
                //increase user_posts...
                $sync->add('user', $this->poster_id, 'user_posts', 1);
            }
            if ($this->post_approved) {
                //...and total posts
                set_config('num_posts', $config['num_posts'] + 1, true);
            }
            reindex('reply', $this->post_id, $sql_data['post_text'], $this->post_subject, $this->poster_id, $this->forum_id);
            $db->sql_transaction('commit');
            // Mark this topic as posted to
            markread('post', $this->forum_id, $this->topic_id, $this->post_time, $this->poster_id);
            // Mark this topic as read
            // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
            markread('topic', $this->forum_id, $this->topic_id, time());
            //
            if ($config['load_db_lastread'] && $user->data['is_registered']) {
                $sql = 'SELECT mark_time
					FROM ' . FORUMS_TRACK_TABLE . '
					WHERE user_id = ' . $user->data['user_id'] . '
						AND forum_id = ' . $this->forum_id;
                $result = $db->sql_query($sql);
                $f_mark_time = (int) $db->sql_fetchfield('mark_time');
                $db->sql_freeresult($result);
            } else {
                if ($config['load_anon_lastread'] || $user->data['is_registered']) {
                    $f_mark_time = false;
                }
            }
            if ($config['load_db_lastread'] && $user->data['is_registered'] || $config['load_anon_lastread'] || $user->data['is_registered']) {
                // Update forum info
                $sql = 'SELECT forum_last_post_time
					FROM ' . FORUMS_TABLE . '
					WHERE forum_id = ' . $this->forum_id;
                $result = $db->sql_query($sql);
                $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
                $db->sql_freeresult($result);
                update_forum_tracking_info($this->forum_id, $forum_last_post_time, $f_mark_time, false);
            }
            // Send Notifications
            user_notification('reply', $this->post_subject, $topic_data['topic_title'], $topic_data['forum_name'], $this->forum_id, $this->topic_id, $this->post_id);
        } else {
            //new topic
            $this->_topic = topic::from_post($this);
            $this->_topic->submit(true);
            //PHP4 Compatibility:
            if (version_compare(PHP_VERSION, '5.0.0', '<')) {
                $this->topic_id = $this->_topic->topic_id;
                $this->post_id = $this->_topic->topic_first_post_id;
            }
            $exec_sync = false;
        }
        foreach ($this->attachments as $attachment) {
            $attachment->post_msg_id = $this->post_id;
            $attachment->topic_id = $this->topic_id;
            $attachment->poster_id = $this->poster_id;
            $attachment->in_message = 0;
            $attachment->is_orphan = 0;
            $attachment->submit();
        }
        if ($exec_sync) {
            $sync->execute();
        }
        /*if($sync_topic)
        		{
        			if($this->_topic)
        			{
        				$this->_topic->sync();
        			}
        			else
        			{
        				sync('topic', 'topic_id', $this->topic_id);
        			}
        		}*/
    }
    protected function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
    {
        global $db, $user, $config, $auth, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;
        /**
         * Modify the data for post submitting
         *
         * @event core.modify_submit_post_data
         *
         * @var string containing posting mode value
         * @var string containing post subject value
         * @var string containing post author name
         * @var int containing topic type value
         * @var array with the poll data for the post
         * @var array with the data for the post
         * @var bool indicating if the post will be updated
         * @var bool indicating if the search index will be updated
         * @since 3.1.0-a4
         */
        $vars = array('mode', 'subject', 'username', 'topic_type', 'poll', 'data', 'update_message', 'update_search_index');
        extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
        // We do not handle erasing posts here
        if ($mode == 'delete') {
            return false;
        }
        // User Info
        if ($mode != 'edit' && isset($data['poster_id']) && $data['poster_id'] && $data['poster_id'] != ANONYMOUS && $data['poster_id'] != $user->data['user_id']) {
            $userdata = $this->get_userdata($data['poster_id']);
        } else {
            $userdata = array('username' => $user->data['username'], 'user_colour' => $user->data['user_colour'], 'user_id' => $user->data['user_id'], 'is_registered' => $user->data['is_registered']);
        }
        if (!empty($data['post_time'])) {
            $current_time = $data['post_time'];
        } else {
            $current_time = time();
        }
        if ($mode == 'post') {
            $post_mode = 'post';
            $update_message = true;
        } else {
            if ($mode != 'edit') {
                $post_mode = 'reply';
                $update_message = true;
            } else {
                if ($mode == 'edit') {
                    $post_mode = $data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1 ? 'edit_topic' : ($data['topic_first_post_id'] == $data['post_id'] ? 'edit_first_post' : ($data['topic_last_post_id'] == $data['post_id'] ? 'edit_last_post' : 'edit'));
                }
            }
        }
        // First of all make sure the subject and topic title are having the correct length.
        // To achieve this without cutting off between special chars we convert to an array and then count the elements.
        $subject = truncate_string($subject, 120);
        $data['topic_title'] = truncate_string($data['topic_title'], 120);
        // Collect some basic information about which tables and which rows to update/insert
        $sql_data = $topic_row = array();
        $poster_id = isset($data['poster_id']) ? $data['poster_id'] : (int) $userdata['user_id'];
        // Retrieve some additional information if not present
        if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false)) {
            $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
				FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
				WHERE t.topic_id = p.topic_id
					AND p.post_id = ' . $data['post_id'];
            $result = $db->sql_query($sql);
            $topic_row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            $data['topic_visibility'] = $topic_row['topic_visibility'];
            $data['post_visibility'] = $topic_row['post_visibility'];
        }
        // This variable indicates if the user is able to post or put into the queue
        $post_visibility = isset($data['post_visibility']) ? $data['post_visibility'] : ITEM_APPROVED;
        // MODs/Extensions are able to force any visibility on posts
        if (isset($data['force_approved_state'])) {
            $post_visibility = in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE)) ? (int) $data['force_approved_state'] : $post_visibility;
        }
        if (isset($data['force_visibility'])) {
            $post_visibility = in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE)) ? (int) $data['force_visibility'] : $post_visibility;
        }
        // Start the transaction here
        $db->sql_transaction('begin');
        // Collect Information
        switch ($post_mode) {
            case 'post':
            case 'reply':
                $sql_data[POSTS_TABLE]['sql'] = array('forum_id' => $data['forum_id'], 'poster_id' => (int) $userdata['user_id'], 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_visibility' => $post_visibility, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => $userdata['user_id'] != ANONYMOUS ? $username : '', 'post_subject' => $subject, 'post_text' => $data['message'], 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_postcount' => isset($data['post_postcount']) ? $data['post_postcount'] : 1, 'post_edit_locked' => $data['post_edit_locked']);
                break;
            case 'edit_first_post':
            case 'edit':
            case 'edit_last_post':
            case 'edit_topic':
                // If edit reason is given always display edit info
                // If editing last post then display no edit info
                // If m_edit permission then display no edit info
                // If normal edit display edit info
                // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
                if ($data['post_edit_reason'] || ($post_mode == 'edit' || $post_mode == 'edit_first_post')) {
                    $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
                    $sql_data[POSTS_TABLE]['sql'] = array('post_edit_time' => $current_time, 'post_edit_reason' => $data['post_edit_reason'], 'post_edit_user' => (int) $data['post_edit_user']);
                    $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
                } else {
                    if (!$data['post_edit_reason'] && $mode == 'edit') {
                        $sql_data[POSTS_TABLE]['sql'] = array('post_edit_reason' => '');
                    }
                }
                // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
                // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
                if ($user->data['user_id'] != $poster_id) {
                    $log_subject = $subject ? $subject : $data['topic_title'];
                    add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, !empty($username) ? $username : $user->lang['GUEST'], $data['post_edit_reason']);
                }
                if (!isset($sql_data[POSTS_TABLE]['sql'])) {
                    $sql_data[POSTS_TABLE]['sql'] = array();
                }
                $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('forum_id' => $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => $username && $data['poster_id'] == ANONYMOUS ? $username : '', 'post_subject' => $subject, 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_edit_locked' => $data['post_edit_locked']));
                if ($update_message) {
                    $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
                }
                break;
        }
        $topic_row = array();
        // And the topic ladies and gentlemen
        switch ($post_mode) {
            case 'post':
                $sql_data[TOPICS_TABLE]['sql'] = array('topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, 'forum_id' => $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_posts_approved' => $post_visibility == ITEM_APPROVED ? 1 : 0, 'topic_posts_softdeleted' => $post_visibility == ITEM_DELETED ? 1 : 0, 'topic_posts_unapproved' => $post_visibility == ITEM_UNAPPROVED ? 1 : 0, 'topic_visibility' => $post_visibility, 'topic_delete_user' => $post_visibility != ITEM_APPROVED ? (int) $user->data['user_id'] : 0, 'topic_title' => $subject, 'topic_first_poster_name' => !$userdata['user_id'] != ANONYMOUS && $username ? $username : ($userdata['user_id'] != ANONYMOUS ? $userdata['username'] : ''), 'topic_first_poster_colour' => $userdata['user_colour'], 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'topic_status' => isset($data['topic_status']) ? $data['topic_status'] : ITEM_UNLOCKED);
                if (isset($poll['poll_options']) && !empty($poll['poll_options'])) {
                    $poll_start = $poll['poll_start'] ? $poll['poll_start'] : $current_time;
                    $poll_length = $poll['poll_length'] * 86400;
                    if ($poll_length < 0) {
                        $poll_start = $poll_start + $poll_length;
                        if ($poll_start < 0) {
                            $poll_start = 0;
                        }
                        $poll_length = 1;
                    }
                    $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array('poll_title' => $poll['poll_title'], 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']));
                }
                $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($post_visibility == ITEM_APPROVED ? ', user_posts = user_posts + 1' : '');
                if ($post_visibility == ITEM_APPROVED) {
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1';
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
                } else {
                    if ($post_visibility == ITEM_UNAPPROVED) {
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1';
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
                    } else {
                        if ($post_visibility == ITEM_DELETED) {
                            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1';
                            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
                        }
                    }
                }
                break;
            case 'reply':
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
					topic_bumped = 0,
					topic_bumper = 0' . ($post_visibility == ITEM_APPROVED ? ', topic_posts_approved = topic_posts_approved + 1' : '') . ($post_visibility == ITEM_UNAPPROVED ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') . ($post_visibility == ITEM_DELETED ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') . (!empty($data['attachment_data']) || isset($data['topic_attachment']) && $data['topic_attachment'] ? ', topic_attachment = 1' : '');
                $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($data['post_postcount'] && $post_visibility == ITEM_APPROVED ? ', user_posts = user_posts + 1' : '');
                if ($post_visibility == ITEM_APPROVED) {
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
                } else {
                    if ($post_visibility == ITEM_UNAPPROVED) {
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
                    } else {
                        if ($post_visibility == ITEM_DELETED) {
                            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
                        }
                    }
                }
                break;
            case 'edit_topic':
            case 'edit_first_post':
                if (isset($poll['poll_options'])) {
                    $poll_start = $poll['poll_start'] || empty($poll['poll_options']) ? $poll['poll_start'] : $current_time;
                    $poll_length = $poll['poll_length'] * 86400;
                    if ($poll_length < 0) {
                        $poll_start = $poll_start + $poll_length;
                        if ($poll_start < 0) {
                            $poll_start = 0;
                        }
                        $poll_length = 1;
                    }
                }
                $sql_data[TOPICS_TABLE]['sql'] = array('forum_id' => $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'poll_title' => isset($poll['poll_options']) ? $poll['poll_title'] : '', 'poll_start' => isset($poll['poll_options']) ? $poll_start : 0, 'poll_max_options' => isset($poll['poll_options']) ? $poll['poll_max_options'] : 1, 'poll_length' => isset($poll['poll_options']) ? $poll_length : 0, 'poll_vote_change' => isset($poll['poll_vote_change']) ? $poll['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0));
                break;
        }
        /**
         * Modify sql query data for post submitting
         *
         * @event core.submit_post_modify_sql_data
         *
         * @var array with the data for the post
         * @var array with the poll data for the post
         * @var string containing posting mode value
         * @var bool with the data for the posting SQL query
         * @var string containing post subject value
         * @var int containing topic type value
         * @var string containing post author name
         * @since 3.1.3-RC1
         */
        $vars = array('data', 'poll', 'post_mode', 'sql_data', 'subject', 'topic_type', 'username');
        extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars)));
        // Submit new topic
        if ($post_mode == 'post') {
            $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
            $db->sql_query($sql);
            $data['topic_id'] = $db->sql_nextid();
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
            unset($sql_data[TOPICS_TABLE]['sql']);
        }
        // Submit new post
        if ($post_mode == 'post' || $post_mode == 'reply') {
            if ($post_mode == 'reply') {
                $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
            }
            $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
            $db->sql_query($sql);
            $data['post_id'] = $db->sql_nextid();
            if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED) {
                $sql_data[TOPICS_TABLE]['sql'] = array('topic_last_post_id' => $data['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'], 'topic_last_poster_name' => !$userdata['user_id'] != ANONYMOUS && $username ? $username : ($userdata['user_id'] != ANONYMOUS ? $userdata['username'] : ''), 'topic_last_poster_colour' => $userdata['user_colour'], 'topic_last_post_subject' => (string) $subject);
            }
            if ($post_mode == 'post') {
                $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id'];
            }
            // Update total post count and forum information
            if ($post_visibility == ITEM_APPROVED) {
                if ($post_mode == 'post') {
                    set_config_count('num_topics', 1, true);
                }
                set_config_count('num_posts', 1, true);
                //TODO Name & Color
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (isset($data['poster_id']) && $data['poster_id'] ? $data['poster_id'] : (int) $userdata['user_id']);
                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . ($userdata['user_id'] == ANONYMOUS ? $username : $userdata['username']) . "'";
                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($userdata['user_colour']) . "'";
            }
            unset($sql_data[POSTS_TABLE]['sql']);
        }
        // Update the topics table
        if (isset($sql_data[TOPICS_TABLE]['sql'])) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
				WHERE topic_id = ' . $data['topic_id'];
            $db->sql_query($sql);
            unset($sql_data[TOPICS_TABLE]['sql']);
        }
        // Update the posts table
        if (isset($sql_data[POSTS_TABLE]['sql'])) {
            $sql = 'UPDATE ' . POSTS_TABLE . '
				SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
				WHERE post_id = ' . $data['post_id'];
            $db->sql_query($sql);
            unset($sql_data[POSTS_TABLE]['sql']);
        }
        // Update Poll Tables
        if (isset($poll['poll_options'])) {
            $cur_poll_options = array();
            if ($mode == 'edit') {
                $sql = 'SELECT *
					FROM ' . POLL_OPTIONS_TABLE . '
					WHERE topic_id = ' . $data['topic_id'] . '
					ORDER BY poll_option_id';
                $result = $db->sql_query($sql);
                $cur_poll_options = array();
                while ($row = $db->sql_fetchrow($result)) {
                    $cur_poll_options[] = $row;
                }
                $db->sql_freeresult($result);
            }
            $sql_insert_ary = array();
            for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) {
                if (strlen(trim($poll['poll_options'][$i]))) {
                    if (empty($cur_poll_options[$i])) {
                        // If we add options we need to put them to the end to be able to preserve votes...
                        $sql_insert_ary[] = array('poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), 'topic_id' => (int) $data['topic_id'], 'poll_option_text' => (string) $poll['poll_options'][$i]);
                    } else {
                        if ($poll['poll_options'][$i] != $cur_poll_options[$i]) {
                            $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "\n\t\t\t\t\t\tSET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'\n\t\t\t\t\t\tWHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
						AND topic_id = ' . $data['topic_id'];
                            $db->sql_query($sql);
                        }
                    }
                }
            }
            $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
            if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) {
                $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
					WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
						AND topic_id = ' . $data['topic_id'];
                $db->sql_query($sql);
            }
            // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
            if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) {
                $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
                $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
            }
        }
        // Submit Attachments
        if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) {
            $space_taken = $files_added = 0;
            $orphan_rows = array();
            foreach ($data['attachment_data'] as $pos => $attach_row) {
                $orphan_rows[(int) $attach_row['attach_id']] = array();
            }
            if (sizeof($orphan_rows)) {
                $sql = 'SELECT attach_id, filesize, physical_filename
			FROM ' . ATTACHMENTS_TABLE . '
					WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
						AND is_orphan = 1
						AND poster_id = ' . $user->data['user_id'];
                $result = $db->sql_query($sql);
                $orphan_rows = array();
                while ($row = $db->sql_fetchrow($result)) {
                    $orphan_rows[$row['attach_id']] = $row;
                }
                $db->sql_freeresult($result);
            }
            foreach ($data['attachment_data'] as $pos => $attach_row) {
                if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) {
                    continue;
                }
                if (!$attach_row['is_orphan']) {
                    // update entry in db if attachment already stored in db and filespace
                    $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "\n\t\t\t\t\t\tSET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'\n\t\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'] . '
							AND is_orphan = 0';
                    $db->sql_query($sql);
                } else {
                    // insert attachment into db
                    if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) {
                        continue;
                    }
                    $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
                    $files_added++;
                    $attach_sql = array('post_msg_id' => $data['post_id'], 'topic_id' => $data['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment']);
                    $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
						WHERE attach_id = ' . $attach_row['attach_id'] . '
						AND is_orphan = 1
							AND poster_id = ' . $user->data['user_id'];
                    $db->sql_query($sql);
                }
            }
            if ($space_taken && $files_added) {
                set_config_count('upload_dir_size', $space_taken, true);
                set_config_count('num_files', $files_added, true);
            }
        }
        $first_post_has_topic_info = $post_mode == 'edit_first_post' && ($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1 || $post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1 || $post_visibility == ITEM_REAPPROVE && $data['topic_posts_unapproved'] == 1 || $post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1);
        // Fix the post's and topic's visibility and first/last post information, when the post is edited
        if ($post_mode != 'post' && $post_mode != 'reply' && $data['post_visibility'] != $post_visibility) {
            // If the post was not approved, it could also be the starter,
            // so we sync the starter after approving/restoring, to ensure that the stats are correct
            // Same applies for the last post
            $is_starter = $post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED;
            $is_latest = $post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED;
            $phpbb_content_visibility = $phpbb_container->get('content.visibility');
            $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $userdata['user_id'], time(), '', $is_starter, $is_latest);
        } else {
            if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info) {
                if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility) {
                    // only the subject can be changed from edit
                    $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
                    // Maybe not only the subject, but also changing anonymous usernames. ;)
                    if ($data['poster_id'] == ANONYMOUS) {
                        $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
                    }
                    if ($post_visibility == ITEM_APPROVED) {
                        // this does not _necessarily_ mean that we must update the info again,
                        // it just means that we might have to
                        $sql = 'SELECT forum_last_post_id, forum_last_post_subject
						FROM ' . FORUMS_TABLE . '
						WHERE forum_id = ' . (int) $data['forum_id'];
                        $result = $db->sql_query($sql);
                        $row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        // this post is the latest post in the forum, better update
                        if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) {
                            // the post's subject changed
                            if ($row['forum_last_post_subject'] !== $subject) {
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
                            }
                            // Update the user name if poster is anonymous... just in case a moderator changed it
                            if ($data['poster_id'] == ANONYMOUS) {
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
                            }
                        }
                    }
                }
            }
        }
        // Update forum stats
        $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id);
        foreach ($sql_data as $table => $update_ary) {
            if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) {
                $sql = "UPDATE {$table} SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
                $db->sql_query($sql);
            }
        }
        // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
        if ($topic_type == POST_GLOBAL) {
            $sql = 'DELETE FROM ' . TOPICS_TABLE . '
							WHERE topic_moved_id = ' . $data['topic_id'];
            $db->sql_query($sql);
        }
        // Committing the transaction before updating search index
        $db->sql_transaction('commit');
        // Delete draft if post was loaded...
        $draft_id = request_var('draft_loaded', 0);
        if ($draft_id) {
            $sql = 'DELETE FROM ' . DRAFTS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE draft_id = {$draft_id}\n\t\t\t\t\t\t\t\tAND user_id = {$user->data['user_id']}";
            $db->sql_query($sql);
        }
        // Index message contents
        if ($update_search_index && $data['enable_indexing']) {
            // Select the search method and do some additional checks to ensure it can actually be utilised
            $search_type = $config['search_type'];
            if (!class_exists($search_type)) {
                trigger_error('NO_SUCH_SEARCH_MODULE');
            }
            $error = false;
            $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
            if ($error) {
                trigger_error($error);
            }
            $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']);
        }
        // Topic Notification, do not change if moderator is changing other users posts...
        if ($userdata['user_id'] == $poster_id) {
            if (!$data['notify_set'] && $data['notify']) {
                $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
					VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
                $db->sql_query($sql);
            } else {
                if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify']) {
                    $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
					WHERE user_id = ' . $user->data['user_id'] . '
						AND topic_id = ' . $data['topic_id'];
                    $db->sql_query($sql);
                }
            }
        }
        if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') {
            // Mark this topic as posted to
            markread('post', $data['forum_id'], $data['topic_id']);
        }
        // Mark this topic as read
        // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
        markread('topic', $data['forum_id'], $data['topic_id'], time());
        //
        if ($config['load_db_lastread'] && $userdata['is_registered']) {
            $sql = 'SELECT mark_time
					FROM ' . FORUMS_TRACK_TABLE . '
					WHERE user_id = ' . $userdata['user_id'] . '
				AND forum_id = ' . $data['forum_id'];
            $result = $db->sql_query($sql);
            $f_mark_time = (int) $db->sql_fetchfield('mark_time');
            $db->sql_freeresult($result);
        } else {
            if ($config['load_anon_lastread'] || $userdata['is_registered']) {
                $f_mark_time = false;
            }
        }
        if ($config['load_db_lastread'] && $user->data['is_registered'] || $config['load_anon_lastread'] || $userdata['is_registered']) {
            // Update forum info
            $sql = 'SELECT forum_last_post_time
				FROM ' . FORUMS_TABLE . '
				WHERE forum_id = ' . $data['forum_id'];
            $result = $db->sql_query($sql);
            $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
            $db->sql_freeresult($result);
            update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
        }
        // If a username was supplied or the poster is a guest, we will use the supplied username.
        // Doing it this way we can use "...post by guest-username..." in notifications when
        // "guest-username" is supplied or ommit the username if it is not.
        $username = $username !== '' || !$userdata['is_registered'] ? $username : $userdata['username'];
        // Send Notifications
        $notification_data = array_merge($data, array('topic_title' => isset($data['topic_title']) ? $data['topic_title'] : $subject, 'post_username' => $username, 'poster_id' => $poster_id, 'post_text' => $data['message'], 'post_time' => $current_time, 'post_subject' => $subject));
        $phpbb_notifications = $phpbb_container->get('notification_manager');
        if ($post_visibility == ITEM_APPROVED) {
            switch ($mode) {
                case 'post':
                    $phpbb_notifications->add_notifications(array('notification.type.quote', 'notification.type.topic'), $notification_data);
                    break;
                case 'reply':
                case 'quote':
                    $phpbb_notifications->add_notifications(array('notification.type.quote', 'notification.type.bookmark', 'notification.type.post'), $notification_data);
                    break;
                case 'edit_topic':
                case 'edit_first_post':
                case 'edit':
                case 'edit_last_post':
                    $phpbb_notifications->update_notifications(array('notification.type.quote', 'notification.type.bookmark', 'notification.type.topic', 'notification.type.post'), $notification_data);
                    break;
            }
        } else {
            if ($post_visibility == ITEM_UNAPPROVED) {
                switch ($mode) {
                    case 'post':
                        $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
                        break;
                    case 'reply':
                    case 'quote':
                        $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
                        break;
                    case 'edit_topic':
                    case 'edit_first_post':
                    case 'edit':
                    case 'edit_last_post':
                        // Nothing to do here
                        break;
                }
            } else {
                if ($post_visibility == ITEM_REAPPROVE) {
                    switch ($mode) {
                        case 'edit_topic':
                        case 'edit_first_post':
                            $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
                            // Delete the approve_post notification so we can notify the user again,
                            // when his post got reapproved
                            $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
                            break;
                        case 'edit':
                        case 'edit_last_post':
                            $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
                            // Delete the approve_post notification so we can notify the user again,
                            // when his post got reapproved
                            $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
                            break;
                        case 'post':
                        case 'reply':
                        case 'quote':
                            // Nothing to do here
                            break;
                    }
                } else {
                    if ($post_visibility == ITEM_DELETED) {
                        switch ($mode) {
                            case 'post':
                            case 'reply':
                            case 'quote':
                            case 'edit_topic':
                            case 'edit_first_post':
                            case 'edit':
                            case 'edit_last_post':
                                // Nothing to do here
                                break;
                        }
                    }
                }
            }
        }
        $params = $add_anchor = '';
        if ($post_visibility == ITEM_APPROVED) {
            $params .= '&amp;t=' . $data['topic_id'];
            if ($mode != 'post') {
                $params .= '&amp;p=' . $data['post_id'];
                $add_anchor = '#p' . $data['post_id'];
            }
        } else {
            if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') {
                $params .= '&amp;t=' . $data['topic_id'];
            }
        }
        $url = !$params ? "{$phpbb_root_path}viewforum.{$phpEx}" : "{$phpbb_root_path}viewtopic.{$phpEx}";
        $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
        /**
         * This event is used for performing actions directly after a post or topic
         * has been submitted.
         * When a new topic is posted, the topic ID is
         * available in the $data array.
         *
         * The only action that can be done by altering data made available to this
         * event is to modify the return URL ($url).
         *
         * @event core.submit_post_end
         *
         * @var string containing posting mode value
         * @var string containing post subject value
         * @var string containing post author name
         * @var int containing topic type value
         * @var array with the poll data for the post
         * @var array with the data for the post
         * @var int containing up to date post visibility
         * @var bool indicating if the post will be updated
         * @var bool indicating if the search index will be updated
         * @var string "Return to topic" URL
         *
         * @since 3.1.0-a3
         *        @change 3.1.0-RC3 Added vars mode, subject, username, topic_type,
         *        poll, update_message, update_search_index
         */
        $vars = array('mode', 'subject', 'username', 'topic_type', 'poll', 'data', 'post_visibility', 'update_message', 'update_search_index', 'url');
        extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
        return $data;
    }