' . 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
// TODO: check this acl_get
if ($not_moderator || !$auth->acl_get('m_'))
{
trigger_error('Not_Moderator');
}
else
{
// TODO: drop this and deal with each mode individually?
$forumless_modes = array('front', 'post_reports', 'mod_queue', 'viewlogs');
if ($mode != '' && !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(
array(
'mode' => 'front',
'title' => $user->lang['FRONT_PAGE'],
'url' => $mcp_url . '&mode=front'
),
array(
'mode' => 'mod_queue',
'title' => $user->lang['MOD_QUEUE'],
'url' => $mcp_url . '&f=' . $forum_id . '&mode=mod_queue'
),
array(
'mode' => 'post_reports',
'title' => $user->lang['REPORTED_POSTS'],
'url' => $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 : '';
$return_mcp = '
' . sprintf($user->lang['RETURN_MCP'], '', '');
if ($forum_id && $forum_data[$forum_id]['forum_postable'] && $auth->acl_get('m_', $forum_id))
{
$tabs[] = array(
'mode' => 'forum_view',
'title' => $user->lang['VIEW_FORUM'],
'url' => $mcp_url . '&mode=forum_view'
);
}
if ($topic_id && $auth->acl_gets('m_delete', 'm_split', 'm_merge', 'm_approve', $forum_id))
{
$tabs[] = array(
'mode' => 'topic_view',
'title' => $user->lang['VIEW_TOPIC'],
'url' => $mcp_url . '&mode=topic_view'
);
}
$tabs[] = array(
'mode' => 'viewlogs',
'title' => ($topic_id) ? $user->lang['VIEW_TOPIC_LOGS'] : $user->lang['VIEW_LOGS'],
'url' => $mcp_url . '&mode=viewlogs'
);
if ($post_id && $auth->acl_gets('m_', $forum_id))
{
$tabs[] = array(
'mode' => 'post_details',
'title' => $user->lang['POST_DETAILS'],
'url' => $mcp_url . '&mode=post_details'
);
}
if ($forum_id > 0 && !$forum_info['forum_postable'])
{
// TODO: re-arrange
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[] = array(
'mode' => 'merge',
'title' => $user->lang['MERGE_TOPIC'],
'url' => $mcp_url . '&mode=merge' . $url_extra
);
}
break;
case 'merge':
case 'split':
$tabs[] = array(
'mode' => $mode,
'title' => $user->lang[strtoupper($mode) . '_TOPIC'],
'url' => $mcp_url . '&mode=' . $mode . $url_extra
);
break;
}
foreach ($tabs as $tab)
{
$template->assign_block_vars('tab', array(
'S_IS_SELECTED' => ($tab['mode'] == $mode) ? TRUE : FALSE,
'NAME' => $tab['title'],
'U_LINK' => $tab['url']
));
}
//
// 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
// - 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.
//
// TODO:
// - post_details Displays post details. Has quick links to (un)approve post.
// - 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':
if (!$to_forum_id && $topic_info['forum_id'] == 0 && $mode != 'make_global')
{
$template->assign_vars(array(
'S_MCP_ACTION' => "mcp.$phpEx$SID&mode=$mode&t=$topic_id",
'S_FORUM_SELECT' => make_forum_select()
));
mcp_header('mcp_unglobalise.html', 'f_post');
include($phpbb_root_path . 'includes/page_tail.' . $phpEx);
}
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 'make_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':
// NOTE: what happens if the user disapproves the first post of the topic? Answer: the topic is deleted
$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'] . '
' . $l_redirect);
}
if ($confirm)
{
$topic_ids = $post_ids = array();
foreach ($post_id_list as $p_id)
{
if ($topic_data[$post_data[$p_id]['topic_id']]['topic_first_post_id'] == $p_id)
{
$topic_ids[] = $post_data[$p_id]['topic_id'];
}
else
{
$post_ids[] = $p_id;
}
}
foreach ($post_id_list as $p_id)
{
if (!in_array($topic_ids, $post_data[$p_id]['topic_id']))
{
$post_ids[] = $p_id;
}
}
if (count($topic_ids))
{
delete_topics('topic_id', $topic_ids);
}
if (count($post_ids))
{
delete_posts('post_id', $post_ids);
}
$template->assign_vars(array(
'META' => '')
);
// TODO: warn the user when post is disapproved
$msg = (count($post_id_list) == 1) ? $user->lang['POST_REMOVED'] : $user->lang['POSTS_REMOVED'];
trigger_error($msg . '
' . $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'] . '