admincp_postsplit.php 13.4 KB
<?php

/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: admincp_postsplit.php 33060 2013-04-16 09:00:06Z zhengqingpeng $
 */

if(!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
	exit('Access Denied');
}
define('IN_DEBUG', false);

@set_time_limit(0);
define('MAX_POSTS_MOVE', 100000);
cpheader();
$topicperpage = 50;

if(empty($operation)) {
	$operation = 'manage';
}

$setting = C::t('common_setting')->fetch_all(array('posttable_info', 'posttableids', 'threadtableids'), true);
if($setting['posttable_info']) {
	$posttable_info = $setting['posttable_info'];
} else {
	$posttable_info = array();
	$posttable_info[0]['type'] = 'primary';
}
$posttableids = $setting['posttableids'] ? $setting['posttableids'] : array();
$threadtableids = $setting['threadtableids'];

if($operation == 'manage') {
	shownav('founder', 'nav_postsplit');
	if(!submitcheck('postsplit_manage')) {

		showsubmenu('nav_postsplit_manage');
		showtips('postsplit_manage_tips');
		showformheader('postsplit&operation=manage');
		showtableheader();

		showsubtitle(array('postsplit_manage_tablename', 'postsplit_manage_datalength', 'postsplit_manage_table_memo', ''));


		$tablename = C::t('forum_post')->getposttable(0, true);
		$tableid = 0;
		$tablestatus = helper_dbtool::gettablestatus($tablename);
		$postcount = $tablestatus['Rows'];
		$data_length = $tablestatus['Data_length'];
		$index_length = $tablestatus['Index_length'];



		$opstr = '<a href="'.ADMINSCRIPT.'?action=postsplit&operation=split&tableid=0">'.cplang('postsplit_name').'</a>';
		showtablerow('', array('', '', '', 'class="td25"'), array($tablename, $data_length, "<input type=\"text\" class=\"txt\" name=\"memo[0]\" value=\"{$posttable_info[0]['memo']}\" />", $opstr));

		foreach(C::t('forum_post')->show_table() as $table) {
			list($tempkey, $tablename) = each($table);
			$tableid = gettableid($tablename);
			if(!preg_match('/^\d+$/', $tableid)) {
				continue;
			}
			$tablestatus = helper_dbtool::gettablestatus($tablename);

			$opstr = '<a href="'.ADMINSCRIPT.'?action=postsplit&operation=split&tableid='.$tableid.'">'.cplang('postsplit_name').'</a>';
			showtablerow('', array('', '', '', 'class="td25"'), array($tablename, $tablestatus['Data_length'], "<input type=\"text\" class=\"txt\" name=\"memo[$tableid]\" value=\"{$posttable_info[$tableid]['memo']}\" />", $opstr));
		}
		showsubmit('postsplit_manage', 'postsplit_manage_update_memo_submit');
		showtablefooter();
		showformfooter();
	} else {
		$posttable_info = array();
		foreach($_GET['memo'] as $key => $value) {
			$key = intval($key);
			$posttable_info[$key]['memo'] = dhtmlspecialchars($value);
		}

		C::t('common_setting')->update('posttable_info', $posttable_info);
		savecache('posttable_info', $posttable_info);
		update_posttableids();
		updatecache('setting');

		cpmsg('postsplit_table_memo_update_succeed', 'action=postsplit&operation=manage', 'succeed');
	}
} elseif($operation == 'split') {

	if(!$_G['setting']['bbclosed']) {
		cpmsg('postsplit_forum_must_be_closed', 'action=postsplit&operation=manage', 'error');
	}

	$tableid = intval($_GET['tableid']);
	$tablename = getposttable($tableid);
	if($tableid && $tablename != 'forum_post' || !$tableid) {
		$status = helper_dbtool::gettablestatus(getposttable($tableid, true), false);
		$allowsplit = false;

		if($status && ((!$tableid && $status['Data_length'] > 400 * 1048576) || ($tableid && $status['Data_length']))) {

			if(!submitcheck('splitsubmit')) {
				showsubmenu('nav_postsplit_manage');
				showtips('postsplit_manage_tips');
				showformheader('postsplit&operation=split&tableid='.$tableid);
				showtableheader();
				showsetting('postsplit_from', '', '', getposttable($tableid, true).(!empty($posttable_info[$tableid]['memo']) ? '('.$posttable_info[$tableid]['memo'].')' : ''));
				$tablelist = '<option value="-1">'.cplang('postsplit_create').'</option>';
				foreach($posttable_info as $tid => $info) {
					if($tableid != $tid) {
						$tablestatus = helper_dbtool::gettablestatus(getposttable($tid, true));
						$tablelist .= '<option value="'.$tid.'">'.($info['memo'] ? $info['memo'] : 'forum_post'.($tid ? '_'.$tid : '')).'('.$tablestatus['Data_length'].')'.'</option>';
					}
				}
				showsetting('postsplit_to', '', '', '<select onchange="if(this.value >= 0) {$(\'tableinfo\').style.display = \'none\';} else {$(\'tableinfo\').style.display = \'\';}" name="targettable">'.$tablelist.'</select>');
				showtagheader('tbody', 'tableinfo', true, 'sub');
				showsetting('postsplit_manage_table_memo', "memo", '', 'text');
				showtagfooter('tbody');

				$datasize = round($status['Data_length'] / 1048576);
				$maxsize = round(($datasize - ($tableid ? 0 : 300)) / 100);
				$maxi = $maxsize > 10 ? 10 : ($maxsize < 1 ? 1 : $maxsize);
				for($i = 1; $i <= $maxi; $i++) {
					$movesize = $i == 10 ? 1024 : $i * 100;
					$maxsizestr .= '<option value="'.$movesize.'">'.($i == 10 ? sizecount($movesize * 1048576) : $movesize.'MB').'</option>';
				}
				showsetting('postsplit_move_size', '', '', '<select name="movesize">'.$maxsizestr.'</select>');

				showsubmit('splitsubmit', 'postsplit_manage_submit');
				showtablefooter();
				showformfooter();
			} else {

				$targettable = intval($_GET['targettable']);
				$createtable = false;
				if($targettable == -1) {
					$maxtableid = getmaxposttableid();
					DB::query('SET SQL_QUOTE_SHOW_CREATE=0', 'SILENT');
					$tableinfo = C::t('forum_post')->show_table_by_tableid(0);
					$createsql = $tableinfo['Create Table'];
					$targettable = $maxtableid + 1;
					$newtable = 'forum_post_'.$targettable;
					$createsql = str_replace(getposttable(), $newtable, $createsql);
					DB::query($createsql);

					$posttable_info[$targettable]['memo'] = $_GET['memo'];
					C::t('common_setting')->update('posttable_info', $posttable_info);
					savecache('posttable_info', $posttable_info);
					update_posttableids();
					$createtable = true;
				}
				$sourcetablearr = gettablefields(getposttable($tableid));
				$targettablearr = gettablefields(getposttable($targettable));
				$fields = array_diff(array_keys($sourcetablearr), array_keys($targettablearr));
				if(!empty($fields)) {
					cpmsg('postsplit_do_error', '', '', array('tableid' => getposttable($targettable, true), 'fields' => implode(',', $fields)));
				}

				$movesize = intval($_GET['movesize']);
				$movesize = $movesize >= 100 && $movesize <= 1024 ? $movesize : 100;
				$targetstatus = helper_dbtool::gettablestatus(getposttable($targettable, true), false);
				$hash = urlencode(authcode("$tableid\t$movesize\t$targettable\t$targetstatus[Data_length]", 'ENCODE'));
				if($createtable) {
					cpmsg('postsplit_table_create_succeed', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettable.'&hash='.$hash, 'loadingform');
				} else {
					cpmsg('postsplit_finish', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettable.'&hash='.$hash, 'loadingform');
				}

			}
		} else {
			cpmsg('postsplit_unallow', 'action=postsplit');
		}
	}

} elseif($operation == 'movepost') {

	if(!$_G['setting']['bbclosed']) {
		cpmsg('postsplit_forum_must_be_closed', 'action=postsplit&operation=manage', 'error');
	}
	list($tableid, $movesize, $targettableid, $sourcesize) = explode("\t", urldecode(authcode($_GET['hash'])));
	$hash = urlencode($_GET['hash']);

	if($tableid == $_GET['fromtable'] && $movesize == $_GET['movesize'] && $targettableid == $_GET['targettable']) {
		$fromtableid = intval($_GET['fromtable']);
		$movesize = intval($_GET['movesize']);
		$targettableid = intval($_GET['targettable']);

		$targettable = gettablefields(getposttable($targettableid));
		$fieldstr = '`'.implode('`, `', array_keys($targettable)).'`';

		loadcache('threadtableids');
		$threadtableids = array(0);
		if(!empty($_G['cache']['threadtableids'])) {
			$threadtableids = array_merge($threadtableids, $_G['cache']['threadtableids']);
		}
		$tableindex = intval(!empty($_GET['tindex']) ? $_GET['tindex'] : 0);
		if(isset($threadtableids[$tableindex])) {

			if(!$fromtableid) {
				$threadtableid = $threadtableids[$tableindex];

				$count = C::t('forum_thread')->count_by_posttableid_displayorder($threadtableid);
				if($count) {
					$tids = array();
					foreach(C::t('forum_thread')->fetch_all_by_posttableid_displayorder($threadtableid) as $tid => $thread) {
						$tids[$tid] = $tid;
					}
					movedate($tids);
				}
				if($tableindex+1 < count($threadtableids)) {
					$tableindex++;
					$status = helper_dbtool::gettablestatus(getposttable($targettableid, true), false);
					$targetsize = $sourcesize + $movesize * 1048576;
					$nowdatasize = $targetsize - $status['Data_length'];

					cpmsg('postsplit_doing', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettableid.'&hash='.$hash.'&tindex='.$tableindex, 'loadingform', array('datalength' => sizecount($status['Data_length']), 'nowdatalength' => sizecount($nowdatasize)));
				}

			} else {
				$count = C::t('forum_post')->count_by_first($fromtableid, 1);
				if($count) {
					$tids = C::t('forum_post')->fetch_all_tid_by_first($fromtableid, 1, 0, 1000);
					movedate($tids);
				} else {
					cpmsg('postsplit_done', 'action=postsplit&operation=optimize&tableid='.$fromtableid, 'form');
				}

			}
		}


	} else {
		cpmsg('postsplit_abnormal', 'action=postsplit', 'succeed');
	}
} elseif($operation == 'optimize') {

	if(!$_G['setting']['bbclosed']) {
		cpmsg('postsplit_forum_must_be_closed', 'action=postsplit&operation=manage', 'error');
	}

	$fromtableid = intval($_GET['tableid']);
	$optimize = true;
	$tablename = getposttable($fromtableid);
	if($fromtableid && $tablename != 'forum_post') {
		$count = C::t('forum_post')->count_table($fromtableid);
		if(!$count) {
			C::t('forum_post')->drop_table($fromtableid);

			unset($posttable_info[$fromtableid]);
			C::t('common_setting')->update('posttable_info', $posttable_info);
			savecache('posttable_info', $posttable_info);
			update_posttableids();
			$optimize = false;
		}

	}
	if($optimize) {
		C::t('forum_post')->optimize_table($fromtableid);
	}
	cpmsg('postsplit_do_succeed', 'action=postsplit', 'succeed');

} elseif($operation == 'pidreset') {
	loadcache('posttableids');
	if(!empty($_G['cache']['posttableids'])) {
		$posttableids = $_G['cache']['posttableids'];
	} else {
		$posttableids = array('0');
	}
	$pidmax = 0;
	foreach($posttableids as $id) {
		if($id == 0) {
			$pidtmp = C::t('forum_post')->fetch_maxid(0);
		} else {
			$pidtmp = C::t('forum_post')->fetch_maxid($id);
		}
		if($pidtmp > $pidmax) {
			$pidmax = $pidtmp;
		}
	}
	$auto_increment = $pidmax + 1;
	C::t('forum_post_tableid')->alter_auto_increment($auto_increment);
	cpmsg('postsplit_resetpid_succeed', 'action=postsplit&operation=manage', 'succeed');
}

function gettableid($tablename) {
	$tableid = substr($tablename, strrpos($tablename, '_') + 1);
	return $tableid;
}

function getmaxposttableid() {
	$maxtableid = 0;
	foreach(C::t('forum_post')->show_table() as $table) {
		list($tempkey, $tablename) = each($table);
		$tableid = intval(gettableid($tablename));
		if($tableid > $maxtableid) {
			$maxtableid = $tableid;
		}
	}
	return $maxtableid;
}

function update_posttableids() {
	$tableids = get_posttableids();
	C::t('common_setting')->update('posttableids', $tableids);
	savecache('posttableids', $tableids);
}

function get_posttableids() {
	$tableids = array(0);
	foreach(C::t('forum_post')->show_table() as $table) {
		list($tempkey, $tablename) = each($table);
		$tableid = gettableid($tablename);
		if(!preg_match('/^\d+$/', $tableid)) {
			continue;
		}
		$tableid = intval($tableid);
		if(!$tableid) {
			continue;
		}
		$tableids[] = $tableid;
	}
	return $tableids;
}



function gettablefields($table) {
	static $tables = array();

	if(!isset($tables[$table])) {
		$tables[$table] = C::t('forum_post')->show_table_columns($table);
	}
	return $tables[$table];
}

function movedate($tids) {
	global $sourcesize, $tableid, $movesize, $targettableid, $hash, $tableindex, $threadtableids, $fieldstr, $fromtableid, $posttable_info;

	$fromtable = getposttable($fromtableid, true);
	C::t('forum_post')->move_table($targettableid, $fieldstr, $fromtable, $tids);
	if(DB::errno()) {
		C::t('forum_post')->delete_by_tid($targettableid, $tids);
	} else {
		foreach($threadtableids as $threadtableid) {
			$affected_rows = C::t('forum_thread')->update($tids, array('posttableid' => $targettableid), false, false, $threadtableid);
			if($affected_rows == count($tids)) {
				break;
			}
		}
		C::t('forum_post')->delete_by_tid($fromtableid, $tids);
	}
	$status = helper_dbtool::gettablestatus(getposttable($targettableid, true), false);
	$targetsize = $sourcesize + $movesize * 1048576;
	$nowdatasize = $targetsize - $status['Data_length'];

	if($status['Data_length'] >= $targetsize) {
		cpmsg('postsplit_done', 'action=postsplit&operation=optimize&tableid='.$fromtableid, 'form');
	}

	cpmsg('postsplit_doing', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettableid.'&hash='.$hash.'&tindex='.$tableindex, 'loadingform', array('datalength' => sizecount($status['Data_length']), 'nowdatalength' => sizecount($nowdatasize)));
}

?>