' . sprintf($user->lang['RETURN_MCP'], '', '');
// Build up return links and acl list
// $acl_src contains the acl list for source forum(s)
// $acl_trg contains the acl list for destination forum(s)
$acl_src = 'm_';
$acl_trg = 'm_';
$return_mode = '
' . sprintf($user->lang['RETURN_MCP'], '', '');
switch ($mode)
{
case 'make_global':
case 'make_announce':
$acl_src = 'f_announce';
break;
case 'make_sticky':
$acl_src = 'f_sticky';
break;
case 'approve':
case 'unapprove':
case 'disapprove':
$acl_src = 'm_approve';
break;
case 'split':
case 'split_all':
case 'split_beyond':
$acl_src = 'a_';
$acl_trg = 'f_post';
$return_mode = '
' . sprintf($user->lang['RETURN_MCP'], '', '');
break;
case 'merge':
case 'merge_posts':
$acl_src = 'm_merge';
$acl_trg = 'm_merge';
$return_mode = '
' . sprintf($user->lang['RETURN_MCP'], '', '');
break;
case 'move':
$acl_src = 'm_move';
$acl_trg = 'f_post';
break;
}
// Check destination forum or topic if applicable
if ($to_topic_id > 0)
{
$result = $db->sql_query('SELECT * FROM ' . TOPICS_TABLE . ' WHERE topic_id = ' . $to_topic_id);
if (!$row = $db->sql_fetchrow($result))
{
trigger_error($user->lang['Topic_not_exist'] . $return_mode);
}
if (!isset($topic_data[$to_topic_id]))
{
$topic_data[$to_topic_id] = $row;
}
$to_forum_id = $row['forum_id'];
}
if ($to_forum_id > 0)
{
if (!isset($forum_data[$to_forum_id]))
{
$result = $db->sql_query('SELECT * FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . $to_forum_id);
if (!$row = $db->sql_fetchrow($result))
{
trigger_error($user->lang['FORUM_NOT_EXIST'] . $return_mode);
}
$forum_data[$to_forum_id] = $row;
}
if (!$auth->acl_get('f_list', $to_forum_id))
{
trigger_error($user->lang['FORUM_NOT_EXIST'] . $return_mode);
}
if (!$auth->acl_gets($acl_trg, $to_forum_id))
{
trigger_error('NOT_ALLOWED');
}
if (!$forum_data[$to_forum_id]['forum_postable'])
{
trigger_error($user->lang['FORUM_NOT_POSTABLE'] . $return_mode);
}
}
// Reset id lists then rebuild them from verified data
$topic_id_sql = implode(', ', array_unique($topic_id_list));
$post_id_sql = implode(', ', array_unique($post_id_list));
$forum_id_list = $topic_id_list = $post_id_list = array();
$not_moderator = FALSE;
if ($forum_id > 0)
{
if ($auth->acl_gets($acl_src, $forum_id))
{
$forum_id_list[] = $forum_id;
}
else
{
$not_moderator = TRUE;
}
}
if ($topic_id_sql)
{
$sql = 'SELECT *
FROM ' . TOPICS_TABLE . "
WHERE topic_id IN ($topic_id_sql)";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
if ($auth->acl_gets($acl_src, $row['forum_id']))
{
$forum_id_list[] = $row['forum_id'];
$topic_id_list[] = $row['topic_id'];
$topic_data[$row['topic_id']] = $row;
}
else
{
$not_moderator = TRUE;
}
}
$db->sql_freeresult($result);
}
if ($post_id_sql)
{
$sql = 'SELECT *
FROM ' . POSTS_TABLE . "
WHERE post_id IN ($post_id_sql)";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
if ($auth->acl_gets($acl_src, $row['forum_id']))
{
$forum_id_list[] = $row['forum_id'];
$topic_id_list[] = $row['topic_id'];
$post_id_list[] = $row['post_id'];
$post_data[$row['post_id']] = $row;
}
else
{
$not_moderator = TRUE;
}
}
$db->sql_freeresult($result);
}
$forum_id_list = array_unique($forum_id_list);
$topic_id_list = array_unique($topic_id_list);
$post_id_list = array_unique($post_id_list);
if (count($forum_id_list))
{
$sql = 'SELECT *
FROM ' . FORUMS_TABLE . '
WHERE forum_id IN (' . implode(', ', $forum_id_list) . ')';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$forum_data[$row['forum_id']] = $row;
}
$db->sql_freeresult($result);
// Set infos about current forum/topic/post
// Uses each() because array_unique may unset index 0 if it's a duplicate
if (!$forum_id && count($forum_id_list) == 1)
{
list($void, $forum_id) = each($forum_id_list);
}
if (!$topic_id && count($topic_id_list) == 1)
{
list($void, $topic_id) = each($topic_id_list);
}
if (!$post_id && count($post_id_list) == 1)
{
list($void, $post_id) = each($post_id_list);
}
$forum_info = $forum_data[$forum_id];
$topic_info = $topic_data[$topic_id];
$post_info = $post_data[$post_id];
}
else
{
// There's no forums list available so the user either submitted an empty or invalid list of posts/topics or isn't a moderator
if ($not_moderator || !$auth->acl_get('m_'))
{
trigger_error('Not_Moderator');
}
else
{
$forumless_modes = array('', 'front', 'post_reports', 'mod_queue');
if (!in_array($mode, $forumless_modes))
{
// The user has submitted invalid post_ids or topic_ids
trigger_error($user->lang['TOPIC_NOT_EXIST'] . $return_mcp);
}
}
}
//
// There we're done validating input.
//
// $post_id_list contains the complete list of post_id's, same for $topic_id_list and $forum_id_list
// $post_id, $topic_id, $forum_id have all been set.
//
// $forum_data is an array where $forum_data[] contains the corresponding row, same for $topic_data and $post_data.
// $forum_info is set to $forum_data[$forum_id] for quick reference, same for topic and post.
//
// We know that the user has m_ or a_ access to all the selected forums/topics/posts but we still have to check for specific authorisations.
//
// Build links and tabs
$mcp_url = "mcp.$phpEx$SID";
$tabs = array(
'front' => $mcp_url,
'mod_queue' => $mcp_url . '&f=' . $forum_id . '&mode=mod_queue',
'post_reports' => $mcp_url . '&f=' . $forum_id . '&mode=post_reports'
);
$mcp_url .= ($forum_id) ? '&f=' . $forum_id : '';
$mcp_url .= ($topic_id) ? '&t=' . $topic_id : '';
$mcp_url .= ($post_id) ? '&p=' . $post_id : '';
//$mcp_url .= ($start) ? '&start=' . $start : '';
$return_mcp = '
' . sprintf($user->lang['RETURN_MCP'], '', '');
if ($forum_id && $forum_data[$forum_id]['forum_postable'] && $auth->acl_get('m_', $forum_id))
{
$tabs['forum_view'] = $mcp_url . '&mode=forum_view';
}
if ($topic_id && $auth->acl_gets('m_delete', 'm_split', 'm_merge', 'm_approve', $forum_id))
{
$tabs['topic_view'] = $mcp_url . '&mode=topic_view' . $url_extra;
}
if ($post_id && $auth->acl_gets('m_', $forum_id))
{
$tabs['post_details'] = $mcp_url . '&mode=post_details';
}
if ($forum_id > 0 && !$forum_info['forum_postable'])
{
if ($mode)
{
trigger_error($user->lang['FORUM_NOT_POSTABLE'] . $return_mcp);
}
else
{
$mode = 'front';
}
}
if (!$mode)
{
if ($post_id)
{
$mode = 'post_details';
}
elseif ($topic_id)
{
$mode = 'topic_view';
}
elseif ($forum_id)
{
$mode = 'forum_view';
}
else
{
$mode = 'front';
}
}
switch ($mode)
{
case 'select_topic':
if ($url_extra)
{
$tabs['merge'] = $mcp_url . '&mode=merge' . $url_extra;
}
break;
case 'merge':
case 'split':
$tabs[$mode] = $mcp_url . '&=' . $mode . $url_extra;
break;
}
// Get the current tab from the mode
// TODO: find a better way to handle this
$tabs_mode = array(
'mod_queue' => 'mod_queue',
'post_reports' => 'post_reports',
'split' => 'split',
'merge' => 'merge',
'ip' => 'post_details',
'forum_view' => 'forum_view',
'topic_view' => 'topic_view',
'post_details' => 'post_details',
'topic_details' => 'topic_details',
'front' => 'front'
);
foreach ($tabs as $tab_name => $tab_link)
{
$template->assign_block_vars('tab', array(
'S_IS_SELECTED' => (!empty($tabs_mode[$mode]) && $tab_name == $tabs_mode[$mode]) ? TRUE : FALSE,
'NAME' => $user->lang['mod_tabs'][$tab_name],
'U_LINK' => $tab_link
));
}
// Post ordering options
// Trying to centralize this a little bit ;) - Ashe
$limit_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 364 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
$sort_by_sql = array('a' => 'u.username', 't' => 'p.post_id', 's' => 'p.post_subject');
$sort_days = (!empty($_REQUEST['st'])) ? max(intval($_REQUEST['st']), 0) : 0;
$sort_key = (!empty($_REQUEST['sk'])) ? htmlspecialchars($_REQUEST['sk']) : 't';
$sort_dir = (!empty($_REQUEST['sd'])) ? htmlspecialchars($_REQUEST['sd']) : 'a';
$sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
$s_limit_days = $s_sort_key = $s_sort_dir = '';
gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir);
$template->assign_vars(array(
'S_SELECT_SORT_DIR' => $s_sort_dir,
'S_SELECT_SORT_KEY' => $s_sort_key,
'S_SELECT_SORT_DAYS'=> $s_limit_days
));
if ($sort_days)
{
$min_post_time = time() - ($sort_days * 86400);
if ($mode == 'mod_queue')
{
$where_sql = ($forum_id) ? 'WHERE forum_id = ' . $forum_id . ' AND': 'WHERE';
}
else
{
$where_sql = 'WHERE topic_id = ' . $topic_id . ' AND';
}
$sql = 'SELECT COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . "
$where_sql post_time >= $min_post_time";
$result = $db->sql_query($sql);
$total_posts = ($row = $db->sql_fetchrow($result)) ? $row['num_posts'] : 0;
$limit_posts_time = "AND p.post_time >= $min_post_time ";
}
else
{
$limit_posts_time = '';
$total_posts = $topic_info['topic_replies'] + 1;
}
//
// Do major work ...
//
// Current modes:
// - make_* Change topic type
// - resync Resyncs topics
// - delete_posts Delete posts, displays confirmation if unconfirmed
// - delete_topics Delete topics, displays confirmation
// - select_topic Forward the user to forum view to select a destination topic for the merge
// - merge Topic view, only displays the Merge button
// - split Topic view, only displays the split buttons
// - delete Topic view, only displays the Delete button
// - topic_view Topic view, similar to viewtopic.php
// - forum_view Forum view, similar to viewforum.php
// - move Move selected topic(s), displays the forums list for confirmation. Used for quickmod as well
// - lock, unlock Lock or unlock topic(s). No confirmation. Used for quickmod.
// - merge_posts Actually merge posts to selected topic. Untested yet.
// - ip Displays poster's ip and other ips the user has posted from. (imported straight from 2.0.x)
// - split_all Actually split selected topic
// - split_beyond Actually split selected topic
//
// TODO:
// - post_details Displays post details. Has quick links to (un)approve post.
// - mod_queue Displays a list or unapproved posts and/or topics. I haven't designed the interface yet but it will have to be able to filter/order them by type (posts/topics), by timestamp or by forum.
// - post_reports Displays a list of reported posts. No interface yet, must be able to order them by priority(?), type, timestamp or forum. Action: view all (default), read, delete.
// - notes Displays moderators notes for current forum or for all forums the user is a moderator of. Actions: view all (default), read, add, delete, edit(?).
// - a hell lot of other things
//
switch ($mode)
{
case 'make_global':
case 'make_announce':
case 'make_sticky':
case 'make_normal':
switch ($mode)
{
case 'make_global':
$set_sql = 'topic_type = ' . POST_ANNOUNCE . ', forum_id = 0';
break;
case 'make_announce':
$set_sql = 'topic_type = ' . POST_ANNOUNCE;
break;
case 'smake_sticky':
$set_sql = 'topic_type = ' . POST_STICKY;
break;
case 'make_normal':
$set_sql = 'topic_type = ' . POST_STICKY;
break;
}
$sql = 'UPDATE ' . TOPICS_TABLE . "
SET $set_sql
WHERE topic_id IN (" . implode(', ', $topic_id_list) . ')';
$db->sql_query($sql);
$return_forum = sprintf($user->lang['RETURN_FORUM'], "", '');
$return_topic = sprintf($user->lang['RETURN_TOPIC'], "", '');
$template->assign_vars(array(
'META' => ""
));
add_log('mod', $forum_id, $topic_id, 'logm_' . $mode);
trigger_error($user->lang['TOPIC_TYPE_CHANGED'] . '
' . $return_topic . '
' . $return_forum);
break;
case 'disapprove':
break;
case 'approve':
case 'unapprove':
$user_posts = $resync_count = array();
$value = ($mode == 'approve') ? 1 : 0;
if (count($post_id_list))
{
$sql = 'UPDATE ' . POSTS_TABLE . "
SET post_approved = $value
WHERE post_id IN (" . implode(', ', $post_id_list) . ')';
$db->sql_query($sql);
if (count($post_id_list) == 1)
{
$lang_str = ($mode == 'approve') ? 'POST_APPROVED' : 'POST_UNAPPROVED';
}
else
{
$lang_str = ($mode == 'approve') ? 'POSTS_APPROVED' : 'POSTS_UNAPPROVED';
}
$redirect_page = "viewtopic.$phpEx$SID&t=$topic_id&start=$start";
$l_redirect = sprintf($user->lang['RETURN_TOPIC'], '', '');
foreach ($post_id_list as $post_id)
{
if ($post_id == $post_data[$post_id]['topic_first_post_id'])
{
$logm_mode = ($mode == 'approve') ? 'logm_approve_topic' : 'logm_unapprove_topic';
}
else
{
$logm_mode = ($mode == 'approve') ? 'logm_approve_post' : 'logm_unapprove_post';
}
add_log('mod', $forum_id, $post_data[$post_id]['topic_id'], $logm_mode, $post_id);
//NOTE: hey, who removed the enable_post_count field?! lol ^ ^
$forum_data[$post_data[$post_id]['forum_id']]['enable_post_count'] = 1;
if ($forum_data[$post_data[$post_id]['forum_id']]['enable_post_count'])
{
if (isset($user_posts[$post_data[$post_id]['poster_id']]))
{
++$user_posts[$post_data[$post_id]['poster_id']];
}
else
{
$user_posts[$post_data[$post_id]['poster_id']] = 1;
}
}
}
}
elseif (count($topic_id_list))
{
// TODO: 20030325 - I'm not sure we will ever use this mode, users won't approve whole topics at once, will they?
$sql = 'UPDATE ' . TOPICS_TABLE . "
SET topic_approved = $value
WHERE topic_id IN (" . implode(', ', $topic_id_list) . ')';
$db->sql_query($sql);
if (count($topic_id_list) == 1)
{
$lang_str = ($mode == 'approve') ? 'TOPIC_APPROVED' : 'TOPIC_UNAPPROVED';
}
else
{
$lang_str = ($mode == 'approve') ? 'TOPICS_APPROVED' : 'TOPICS_UNAPPROVED';
}
$redirect_page = "viewforum.$phpEx$SID&f=$forum_id&start=$start";
$l_redirect = sprintf($user->lang['RETURN_FORUM'], '', '');
$logm_mode = ($mode == 'approve') ? 'logm_approve_topic' : 'logm_unapprove_topic';
foreach ($topic_id_list as $topic_id)
{
add_log('mod', $forum_id, $topic_id, $logm_mode);
}
}
else
{
trigger_error($user->lang['NO_POST_SELECTED']);
}
// Resync last post infos, replies count et caetera
sync('topic', 'topic_id', $topic_id_list);
foreach ($user_posts as $user_id => $post_count)
{
if (isset($resync_count[$post_count]))
{
$resync_count[$post_count][] = $user_id;
}
else
{
$resync_count[$post_count] = array($user_id);
}
}
foreach ($resync_count as $post_count => $user_list)
{
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_posts = user_posts + $post_count
WHERE user_id IN (" . implode(', ', $user_list) . ')';
$db->sql_query($sql);
}
$template->assign_vars(array(
'META' => '')
);
$return_mcp = '
' . $l_redirect);
break;
case 'delete_posts':
// NOTE: what happens if the user deletes the first post of the topic? The topic is resync'ed normally and topic time/topic author are updated by the new first post
$redirect_page = "mcp.$phpEx$SID&f=$forum_id";
$l_redirect = sprintf($user->lang['RETURN_MCP'], '', '');
if (!count($post_id_list))
{
trigger_error($user->lang['NO_POST_SELECTED'] . '