<?php

define('COPYPOST_MAX_COPIES', 5);

if(!defined('IN_MYBB'))
	die('This file cannot be accessed directly.');

$plugins->add_hook('moderation_start', 'copypost_run');
$plugins->add_hook('showthread_start', 'copypost_fixqueries');

function copypost_info()
{
	return array(
		'name'			=> 'Dissect/Duplicate Posts',
		'description'	=> 'This will add an additional moderation tool which allows posts to be duplicated via Inline Post Moderation.  If only one post is selected, the post may be &quot;dissected&quot; or split.',
		'website'		=> 'http://mybbhacks.zingaburga.com/',
		'author'		=> 'ZiNgA BuRgA',
		'authorsite'	=> 'http://zingaburga.com/',
		'version'		=> '1.21',
		'compatibility'	=> '14*,15*,16*',
		//'guid'			=> '18a687eb1478e4d1ba946bcb7323ca2c'
	);
}

define('COPYPOST_TEMPLATE_ADD', '
	<option value="multicopyposts">Duplicate Posts</option>');
function copypost_activate()
{
	global $db;
	
	require MYBB_ROOT."/inc/adminfunctions_templates.php";
	find_replace_templatesets('showthread_inlinemoderation', '#'.preg_quote('<option value="multiunapproveposts">{$lang->inline_unapprove_posts}</option>').'#', '<option value="multiunapproveposts">{$lang->inline_unapprove_posts}</option>'.COPYPOST_TEMPLATE_ADD);
	
	$newtemplate = '<html>
<head>
<title>{$mybb->settings[\'bbname\']} - Duplicate Posts</title>
{$headerinclude}
</head>
<body>
{$header}
<form action="moderation.php" method="post">
<table border="0" cellspacing="{$theme[\'borderwidth\']}" cellpadding="{$theme[\'tablespace\']}" class="tborder">
<tr>
<td class="thead" colspan="2"><strong>Duplicate Post(s)</strong></td>
</tr>
{$loginbox}
{$copypost_content}
</table>
<br />
<div align="center"><input type="submit" class="button" name="submit" value="Duplicate Posts" /></div>
<input type="hidden" name="action" value="do_multicopyposts" />
<input type="hidden" name="tid" value="{$tid}" />
<input type="hidden" name="posts" value="{$inlineids}" />
</form>
{$footer}
</body>
</html>';
	$db->insert_query('templates', array(
		'title' => 'moderation_inline_copyposts',
		'template' => $db->escape_string($newtemplate),
		'sid' => -1,
		'version' => $mybb->version_code
	));
	
	$newtemplate = '<tr>
<td class="{$bgcolor2}" colspan="2" align="center">This tool allows you to dissect the selected post, into multiple posts.  Please enter the new message for each new copy you wish to create.</td>
</tr>
<tr>
<td class="{$bgcolor}" valign="top"><label for="orig_message"><strong>Original Post</strong></label></td>
<td class="{$bgcolor}"><textarea name="orig_message" cols="70" rows="10" id="orig_message">{$postdata[\'message\']}</textarea></td>
</tr>';
	$db->insert_query('templates', array(
		'title' => 'moderation_copyposts_single',
		'template' => $db->escape_string($newtemplate),
		'sid' => -1,
		'version' => $mybb->version_code
	));
	$newtemplate = '<tr>
<td class="trow1"><strong>Number of Copies to make:</strong></td>
<td class="trow1"><input type="text" class="textbox" name="copies" value="1" size="10" maxlen="2" /></td>
</tr>';
	$db->insert_query('templates', array(
		'title' => 'moderation_copyposts_multi',
		'template' => $db->escape_string($newtemplate),
		'sid' => -1,
		'version' => $mybb->version_code
	));
}

function copypost_deactivate()
{
	global $db;
	
	require MYBB_ROOT."/inc/adminfunctions_templates.php";
	find_replace_templatesets('showthread_inlinemoderation', '#'.preg_quote(COPYPOST_TEMPLATE_ADD).'#', '', 0);
	
	$db->delete_query('templates', 'title IN ("moderation_inline_copyposts","moderation_copyposts_single","moderation_copyposts_multi") AND sid=-1');
}

function copypost_run()
{
	global $mybb, $lang, $db;
	if($mybb->input['action'] != 'multicopyposts' && $mybb->input['action'] != 'do_multicopyposts') return;
	$tid = intval($mybb->input['tid']);
	if($tid)
		$thread = get_thread($tid);
	if(!$thread['tid'])
		error($lang->error_invalidthread);
	build_forum_breadcrumb($thread['fid']);
	add_breadcrumb($thread['subject'], get_thread_link($thread['tid']));
	add_breadcrumb('Duplicate Post(s)');
	/*
	$pid = intval($mybb->input['pid']);
	
	if($pid && !$tid)
	{
		$post = get_post($pid);
		$tid = $post['tid'];
		if(!$post['pid'])
			error($lang->error_invalidpost);
	}*/
	
	if(!is_moderator($thread['fid']))
		error_no_permission();
	check_forum_password($thread['fid']);
	
	
	// do our moderation here
	if($mybb->input['action'] == 'do_multicopyposts')
	{
		$pidlist = array_map('intval', explode(',', $mybb->input['posts']));
		foreach($pidlist as $k => $pid) // remove 0 elements
			if(!$pid) unset($pidlist[$k]);
		if(empty($pidlist)) error('No posts selected for duplication!');
		
		// do our duplication!
		$unappr_count = $appr_count = 0;
		if(count($pidlist) == 1 && is_array($mybb->input['msg']))
		{
			$post = array_map(array($db, 'escape_string'), get_post(reset($pidlist)));
			if(!$post['pid']) error('Invalid post specified!');
			$pid = $post['pid'];
			unset($post['pid'], $post['message']);
			
			//foreach($post as $k => $v)
			//	$post[$k] = $db->escape_string($v);
			
			if(!$mybb->input['orig_message'])
				error('The original post MUST have a message!');
			
			foreach($mybb->input['msg'] as $k => $msg)
				if(!$msg)
				{
					unset($mybb->input['msg'][$k]);
					continue;
				}
			
			if(count($mybb->input['msg']) < 1)
				error('You need to have content in subsequent posts for duplication!');
			if(count($mybb->input['msg']) > COPYPOST_MAX_COPIES)
				error('You cannot make that number of duplications!');
			
			// validation done - almost :P
			require_once MYBB_ROOT."inc/datahandlers/post.php";
			$ph = new PostDataHandler("update");
			$ph->action = "post";
			$ph->set_data(array(
				'message' => $mybb->input['orig_message'],
				'edit_uid' => $mybb->user['uid'],
				'uid' => $mybb->user['uid'],
				'username' => $mybb->user['username'],
				'pid' => $pid
			));
			if(!$ph->validate_post())
			{
				$post_errors = $ph->get_friendly_errors();
				error($post_errors);
			}
			$ph->update_post();
			unset($ph);
			
			// we won't bother validating for dupe posts
			foreach($mybb->input['msg'] as $k => $msg)
			{
				$post['message'] = $db->escape_string($msg);
				$db->insert_query('posts', $post);
			}
			
			if($post['visible'] == '1')
				$appr_count += count($mybb->input['msg']);
			elseif($post['visible'] == '0')
				$unappr_count += count($mybb->input['msg']);
			
			// update user's post count
			$forum = get_forum($thread['fid']);
			if($forum['usepostcounts'] != 0 && $appr_count)
				$db->write_query('UPDATE '.$db->table_prefix.'users SET postnum=postnum+'.$appr_count.' WHERE uid='.$post['uid'].' LIMIT 1');
			
			log_moderator_action(array('pid' => $pid, 'tid' => $thread['tid'], 'fid' => $thread['fid']), 'Dissected post.');
			$redirect_msg = 'Selected post successfully dissected!';
		}
		else
		{
			$copies = intval($mybb->input['copies']);
			if($copies < 1) error('You must make at least one copy!');
			if($copies > COPYPOST_MAX_COPIES) error('Sorry, you cannot make that many copies.');
			
			$query = $db->simple_select('posts', '*', 'pid IN ('.implode(',', $pidlist).')');
			$fidposts = array();
			while($post = $db->fetch_array($query))
			{
				//$pid = $post['pid'];
				unset($post['pid']);
				if($post['visible'] == '1')
					$appr_count += $copies;
				elseif($post['visible'] == '0')
					$unappr_count += $copies;
				
				for($i=0; $i<$copies; $i++)
					$db->insert_query('posts', array_map(array($db, 'escape_string'), $post));
				
				$fidposts[$post['fid']][$post['uid']] += $copies;
			}
			
			// update users' post counts too >_>
			$forums = $GLOBALS['cache']->read('forums');
			$useradd = array();
			foreach($fidposts as $fid => $userlist)
				if($forums[$fid]['usepostcounts'] != 0)
					foreach($userlist as $uid => $posts)
						$useradd[$uid] += $posts;
			
			foreach($useradd as $uid => $posts)
			{
				$db->write_query('UPDATE '.$db->table_prefix.'users SET postnum=postnum+'.$posts.' WHERE uid='.$uid.' LIMIT 1');
			}
			
			log_moderator_action(array('tid' => $thread['tid'], 'fid' => $thread['fid']), 'Duplicated posts.');
			$redirect_msg = 'Selected post(s) successfully duplicated!';
		}
		// update thread counters
		if(function_exists('update_thread_counters'))
		{
			update_thread_counters($thread['tid'], array('replies' => '+'.$appr_count, 'unapprovedposts' => '+'.$unappr_count));
			update_forum_counters($thread['fid'], array('posts' => '+'.$appr_count, 'unapprovedposts' => '+'.$unappr_count));
		}
		else
		{ // legacy functions
			update_thread_count($thread['tid']);
			update_forum_count($thread['fid']);
		}
		if($pid) {
			$link = get_post_link($pid, $tid);
			if(!strpos($link, '#')) $link .= '#pid'.$pid;
		}
		else
			$link = get_thread_link($tid);
		redirect($link, $redirect_msg);
	}
	else
	{
		// display duplication page
		$posts = getids($tid, 'thread');
		foreach($posts as $k => $post) // remove 0 elems
			if(!$post) unset($posts[$k]);
		if(empty($posts))
			error($lang->error_inline_nopostsselected);
		$inlineids = implode(',', $posts);
		clearinline($tid, 'thread');
		
		
		global $theme, $templates, $header, $footer, $headerinclude;
		if($mybb->user['uid'])
			eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
		else
			eval("\$loginbox = \"".$templates->get("loginbox")."\";");
		
		if(count($posts) == 1)
		{
			$postdata = get_post(reset($posts));
			$bgcolor2 = alt_trow();
			$bgcolor = alt_trow();
			eval('$copypost_content = "'.$templates->get('moderation_copyposts_single').'";');
			for($i=0; $i<COPYPOST_MAX_COPIES; $i++)
			{
				$bgcolor = alt_trow();
				$copypost_content .= '<tr>
<td class="'.$bgcolor.'" valign="top"><label for="msg_'.$i.'"><strong>Post Copy #'.($i+1).'</strong></label><br /><span class="smalltext">[<a href="javascript:$(\'msg_'.$i.'\').value=$(\'orig_message\').value;void(0);">Copy Original Message</a>]</span></td>
<td class="'.$bgcolor.'"><textarea name="msg['.$i.']" cols="70" rows="10" id="msg_'.$i.'"></textarea></td>
</tr>';
			}
		}
		else
		{
			eval('$copypost_content = "'.$templates->get('moderation_copyposts_multi').'";');
		}
		
		output_page(eval('return "'.$templates->get('moderation_inline_copyposts').'";'));
		
	}
	exit;
}


function copypost_fixqueries()
{
	global $mybb;
	if($mybb->input['pid']) {
		global $post;
		if(empty($post) || $post['pid'] != $mybb->input['pid']) {
			$post2 = get_post($mybb->input['pid']);
			$dateline = $post2['dateline'];
		} else {
			$dateline = $post['dateline'];
		}
		$extra_code = '
			if(strpos($string, "SELECT COUNT(p.pid) AS count FROM") && strpos($string, "AND p.pid <=")) {
				$string = str_replace("AND p.pid <= \''.$mybb->input['pid'].'\'", "AND p.dateline <= \''.$dateline.'\'", $string);
			}
		';
	}
	else {
		$extra_code = '
			if(strpos($string, " ORDER BY dateline LIMIT 0, 1") && strpos($string, "FROM '.TABLE_PREFIX.'posts p")) {
				$string = str_replace("ORDER BY dateline", "ORDER BY dateline, pid", $string);
			}
		';
	}
	control_object($GLOBALS['db'], '
		function query($string, $hide_errors=0, $write_query=0) {
			if(preg_match(\'~^\\s+SELECT .*? FROM '.TABLE_PREFIX.'posts p\\s.*\\sORDER BY p\\.dateline\\s~s\', $string)) {
				$string = str_replace("ORDER BY p.dateline", "ORDER BY p.dateline, p.pid", $string);
			}
			'.$extra_code.'
			return parent::query($string, $hide_errors, $write_query);
		}
	');
}

if(!function_exists('control_object')) {
	function control_object(&$obj, $code) {
		static $cnt = 0;
		$newname = '_objcont_'.(++$cnt);
		$objserial = serialize($obj);
		$classname = get_class($obj);
		$checkstr = 'O:'.strlen($classname).':"'.$classname.'":';
		$checkstr_len = strlen($checkstr);
		if(substr($objserial, 0, $checkstr_len) == $checkstr) {
			$vars = array();
			// grab resources/object etc, stripping scope info from keys
			foreach((array)$obj as $k => $v) {
				if($p = strrpos($k, "\0"))
					$k = substr($k, $p+1);
				$vars[$k] = $v;
			}
			if(!empty($vars))
				$code .= '
					function ___setvars(&$a) {
						foreach($a as $k => &$v)
							$this->$k = $v;
					}
				';
			eval('class '.$newname.' extends '.$classname.' {'.$code.'}');
			$obj = unserialize('O:'.strlen($newname).':"'.$newname.'":'.substr($objserial, $checkstr_len));
			if(!empty($vars))
				$obj->___setvars($vars);
		}
		// else not a valid object or PHP serialize has changed
	}
}

?>