admincp_postsplit.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Comsenz Inc.
  4. * This is NOT a freeware, use is subject to license terms
  5. *
  6. * $Id: admincp_postsplit.php 33060 2013-04-16 09:00:06Z zhengqingpeng $
  7. */
  8. if(!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
  9. exit('Access Denied');
  10. }
  11. define('IN_DEBUG', false);
  12. @set_time_limit(0);
  13. define('MAX_POSTS_MOVE', 100000);
  14. cpheader();
  15. $topicperpage = 50;
  16. if(empty($operation)) {
  17. $operation = 'manage';
  18. }
  19. $setting = C::t('common_setting')->fetch_all(array('posttable_info', 'posttableids', 'threadtableids'), true);
  20. if($setting['posttable_info']) {
  21. $posttable_info = $setting['posttable_info'];
  22. } else {
  23. $posttable_info = array();
  24. $posttable_info[0]['type'] = 'primary';
  25. }
  26. $posttableids = $setting['posttableids'] ? $setting['posttableids'] : array();
  27. $threadtableids = $setting['threadtableids'];
  28. if($operation == 'manage') {
  29. shownav('founder', 'nav_postsplit');
  30. if(!submitcheck('postsplit_manage')) {
  31. showsubmenu('nav_postsplit_manage');
  32. showtips('postsplit_manage_tips');
  33. showformheader('postsplit&operation=manage');
  34. showtableheader();
  35. showsubtitle(array('postsplit_manage_tablename', 'postsplit_manage_datalength', 'postsplit_manage_table_memo', ''));
  36. $tablename = C::t('forum_post')->getposttable(0, true);
  37. $tableid = 0;
  38. $tablestatus = helper_dbtool::gettablestatus($tablename);
  39. $postcount = $tablestatus['Rows'];
  40. $data_length = $tablestatus['Data_length'];
  41. $index_length = $tablestatus['Index_length'];
  42. $opstr = '<a href="'.ADMINSCRIPT.'?action=postsplit&operation=split&tableid=0">'.cplang('postsplit_name').'</a>';
  43. showtablerow('', array('', '', '', 'class="td25"'), array($tablename, $data_length, "<input type=\"text\" class=\"txt\" name=\"memo[0]\" value=\"{$posttable_info[0]['memo']}\" />", $opstr));
  44. foreach(C::t('forum_post')->show_table() as $table) {
  45. list($tempkey, $tablename) = each($table);
  46. $tableid = gettableid($tablename);
  47. if(!preg_match('/^\d+$/', $tableid)) {
  48. continue;
  49. }
  50. $tablestatus = helper_dbtool::gettablestatus($tablename);
  51. $opstr = '<a href="'.ADMINSCRIPT.'?action=postsplit&operation=split&tableid='.$tableid.'">'.cplang('postsplit_name').'</a>';
  52. showtablerow('', array('', '', '', 'class="td25"'), array($tablename, $tablestatus['Data_length'], "<input type=\"text\" class=\"txt\" name=\"memo[$tableid]\" value=\"{$posttable_info[$tableid]['memo']}\" />", $opstr));
  53. }
  54. showsubmit('postsplit_manage', 'postsplit_manage_update_memo_submit');
  55. showtablefooter();
  56. showformfooter();
  57. } else {
  58. $posttable_info = array();
  59. foreach($_GET['memo'] as $key => $value) {
  60. $key = intval($key);
  61. $posttable_info[$key]['memo'] = dhtmlspecialchars($value);
  62. }
  63. C::t('common_setting')->update('posttable_info', $posttable_info);
  64. savecache('posttable_info', $posttable_info);
  65. update_posttableids();
  66. updatecache('setting');
  67. cpmsg('postsplit_table_memo_update_succeed', 'action=postsplit&operation=manage', 'succeed');
  68. }
  69. } elseif($operation == 'split') {
  70. if(!$_G['setting']['bbclosed']) {
  71. cpmsg('postsplit_forum_must_be_closed', 'action=postsplit&operation=manage', 'error');
  72. }
  73. $tableid = intval($_GET['tableid']);
  74. $tablename = getposttable($tableid);
  75. if($tableid && $tablename != 'forum_post' || !$tableid) {
  76. $status = helper_dbtool::gettablestatus(getposttable($tableid, true), false);
  77. $allowsplit = false;
  78. if($status && ((!$tableid && $status['Data_length'] > 400 * 1048576) || ($tableid && $status['Data_length']))) {
  79. if(!submitcheck('splitsubmit')) {
  80. showsubmenu('nav_postsplit_manage');
  81. showtips('postsplit_manage_tips');
  82. showformheader('postsplit&operation=split&tableid='.$tableid);
  83. showtableheader();
  84. showsetting('postsplit_from', '', '', getposttable($tableid, true).(!empty($posttable_info[$tableid]['memo']) ? '('.$posttable_info[$tableid]['memo'].')' : ''));
  85. $tablelist = '<option value="-1">'.cplang('postsplit_create').'</option>';
  86. foreach($posttable_info as $tid => $info) {
  87. if($tableid != $tid) {
  88. $tablestatus = helper_dbtool::gettablestatus(getposttable($tid, true));
  89. $tablelist .= '<option value="'.$tid.'">'.($info['memo'] ? $info['memo'] : 'forum_post'.($tid ? '_'.$tid : '')).'('.$tablestatus['Data_length'].')'.'</option>';
  90. }
  91. }
  92. showsetting('postsplit_to', '', '', '<select onchange="if(this.value >= 0) {$(\'tableinfo\').style.display = \'none\';} else {$(\'tableinfo\').style.display = \'\';}" name="targettable">'.$tablelist.'</select>');
  93. showtagheader('tbody', 'tableinfo', true, 'sub');
  94. showsetting('postsplit_manage_table_memo', "memo", '', 'text');
  95. showtagfooter('tbody');
  96. $datasize = round($status['Data_length'] / 1048576);
  97. $maxsize = round(($datasize - ($tableid ? 0 : 300)) / 100);
  98. $maxi = $maxsize > 10 ? 10 : ($maxsize < 1 ? 1 : $maxsize);
  99. for($i = 1; $i <= $maxi; $i++) {
  100. $movesize = $i == 10 ? 1024 : $i * 100;
  101. $maxsizestr .= '<option value="'.$movesize.'">'.($i == 10 ? sizecount($movesize * 1048576) : $movesize.'MB').'</option>';
  102. }
  103. showsetting('postsplit_move_size', '', '', '<select name="movesize">'.$maxsizestr.'</select>');
  104. showsubmit('splitsubmit', 'postsplit_manage_submit');
  105. showtablefooter();
  106. showformfooter();
  107. } else {
  108. $targettable = intval($_GET['targettable']);
  109. $createtable = false;
  110. if($targettable == -1) {
  111. $maxtableid = getmaxposttableid();
  112. DB::query('SET SQL_QUOTE_SHOW_CREATE=0', 'SILENT');
  113. $tableinfo = C::t('forum_post')->show_table_by_tableid(0);
  114. $createsql = $tableinfo['Create Table'];
  115. $targettable = $maxtableid + 1;
  116. $newtable = 'forum_post_'.$targettable;
  117. $createsql = str_replace(getposttable(), $newtable, $createsql);
  118. DB::query($createsql);
  119. $posttable_info[$targettable]['memo'] = $_GET['memo'];
  120. C::t('common_setting')->update('posttable_info', $posttable_info);
  121. savecache('posttable_info', $posttable_info);
  122. update_posttableids();
  123. $createtable = true;
  124. }
  125. $sourcetablearr = gettablefields(getposttable($tableid));
  126. $targettablearr = gettablefields(getposttable($targettable));
  127. $fields = array_diff(array_keys($sourcetablearr), array_keys($targettablearr));
  128. if(!empty($fields)) {
  129. cpmsg('postsplit_do_error', '', '', array('tableid' => getposttable($targettable, true), 'fields' => implode(',', $fields)));
  130. }
  131. $movesize = intval($_GET['movesize']);
  132. $movesize = $movesize >= 100 && $movesize <= 1024 ? $movesize : 100;
  133. $targetstatus = helper_dbtool::gettablestatus(getposttable($targettable, true), false);
  134. $hash = urlencode(authcode("$tableid\t$movesize\t$targettable\t$targetstatus[Data_length]", 'ENCODE'));
  135. if($createtable) {
  136. cpmsg('postsplit_table_create_succeed', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettable.'&hash='.$hash, 'loadingform');
  137. } else {
  138. cpmsg('postsplit_finish', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettable.'&hash='.$hash, 'loadingform');
  139. }
  140. }
  141. } else {
  142. cpmsg('postsplit_unallow', 'action=postsplit');
  143. }
  144. }
  145. } elseif($operation == 'movepost') {
  146. if(!$_G['setting']['bbclosed']) {
  147. cpmsg('postsplit_forum_must_be_closed', 'action=postsplit&operation=manage', 'error');
  148. }
  149. list($tableid, $movesize, $targettableid, $sourcesize) = explode("\t", urldecode(authcode($_GET['hash'])));
  150. $hash = urlencode($_GET['hash']);
  151. if($tableid == $_GET['fromtable'] && $movesize == $_GET['movesize'] && $targettableid == $_GET['targettable']) {
  152. $fromtableid = intval($_GET['fromtable']);
  153. $movesize = intval($_GET['movesize']);
  154. $targettableid = intval($_GET['targettable']);
  155. $targettable = gettablefields(getposttable($targettableid));
  156. $fieldstr = '`'.implode('`, `', array_keys($targettable)).'`';
  157. loadcache('threadtableids');
  158. $threadtableids = array(0);
  159. if(!empty($_G['cache']['threadtableids'])) {
  160. $threadtableids = array_merge($threadtableids, $_G['cache']['threadtableids']);
  161. }
  162. $tableindex = intval(!empty($_GET['tindex']) ? $_GET['tindex'] : 0);
  163. if(isset($threadtableids[$tableindex])) {
  164. if(!$fromtableid) {
  165. $threadtableid = $threadtableids[$tableindex];
  166. $count = C::t('forum_thread')->count_by_posttableid_displayorder($threadtableid);
  167. if($count) {
  168. $tids = array();
  169. foreach(C::t('forum_thread')->fetch_all_by_posttableid_displayorder($threadtableid) as $tid => $thread) {
  170. $tids[$tid] = $tid;
  171. }
  172. movedate($tids);
  173. }
  174. if($tableindex+1 < count($threadtableids)) {
  175. $tableindex++;
  176. $status = helper_dbtool::gettablestatus(getposttable($targettableid, true), false);
  177. $targetsize = $sourcesize + $movesize * 1048576;
  178. $nowdatasize = $targetsize - $status['Data_length'];
  179. 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)));
  180. }
  181. } else {
  182. $count = C::t('forum_post')->count_by_first($fromtableid, 1);
  183. if($count) {
  184. $tids = C::t('forum_post')->fetch_all_tid_by_first($fromtableid, 1, 0, 1000);
  185. movedate($tids);
  186. } else {
  187. cpmsg('postsplit_done', 'action=postsplit&operation=optimize&tableid='.$fromtableid, 'form');
  188. }
  189. }
  190. }
  191. } else {
  192. cpmsg('postsplit_abnormal', 'action=postsplit', 'succeed');
  193. }
  194. } elseif($operation == 'optimize') {
  195. if(!$_G['setting']['bbclosed']) {
  196. cpmsg('postsplit_forum_must_be_closed', 'action=postsplit&operation=manage', 'error');
  197. }
  198. $fromtableid = intval($_GET['tableid']);
  199. $optimize = true;
  200. $tablename = getposttable($fromtableid);
  201. if($fromtableid && $tablename != 'forum_post') {
  202. $count = C::t('forum_post')->count_table($fromtableid);
  203. if(!$count) {
  204. C::t('forum_post')->drop_table($fromtableid);
  205. unset($posttable_info[$fromtableid]);
  206. C::t('common_setting')->update('posttable_info', $posttable_info);
  207. savecache('posttable_info', $posttable_info);
  208. update_posttableids();
  209. $optimize = false;
  210. }
  211. }
  212. if($optimize) {
  213. C::t('forum_post')->optimize_table($fromtableid);
  214. }
  215. cpmsg('postsplit_do_succeed', 'action=postsplit', 'succeed');
  216. } elseif($operation == 'pidreset') {
  217. loadcache('posttableids');
  218. if(!empty($_G['cache']['posttableids'])) {
  219. $posttableids = $_G['cache']['posttableids'];
  220. } else {
  221. $posttableids = array('0');
  222. }
  223. $pidmax = 0;
  224. foreach($posttableids as $id) {
  225. if($id == 0) {
  226. $pidtmp = C::t('forum_post')->fetch_maxid(0);
  227. } else {
  228. $pidtmp = C::t('forum_post')->fetch_maxid($id);
  229. }
  230. if($pidtmp > $pidmax) {
  231. $pidmax = $pidtmp;
  232. }
  233. }
  234. $auto_increment = $pidmax + 1;
  235. C::t('forum_post_tableid')->alter_auto_increment($auto_increment);
  236. cpmsg('postsplit_resetpid_succeed', 'action=postsplit&operation=manage', 'succeed');
  237. }
  238. function gettableid($tablename) {
  239. $tableid = substr($tablename, strrpos($tablename, '_') + 1);
  240. return $tableid;
  241. }
  242. function getmaxposttableid() {
  243. $maxtableid = 0;
  244. foreach(C::t('forum_post')->show_table() as $table) {
  245. list($tempkey, $tablename) = each($table);
  246. $tableid = intval(gettableid($tablename));
  247. if($tableid > $maxtableid) {
  248. $maxtableid = $tableid;
  249. }
  250. }
  251. return $maxtableid;
  252. }
  253. function update_posttableids() {
  254. $tableids = get_posttableids();
  255. C::t('common_setting')->update('posttableids', $tableids);
  256. savecache('posttableids', $tableids);
  257. }
  258. function get_posttableids() {
  259. $tableids = array(0);
  260. foreach(C::t('forum_post')->show_table() as $table) {
  261. list($tempkey, $tablename) = each($table);
  262. $tableid = gettableid($tablename);
  263. if(!preg_match('/^\d+$/', $tableid)) {
  264. continue;
  265. }
  266. $tableid = intval($tableid);
  267. if(!$tableid) {
  268. continue;
  269. }
  270. $tableids[] = $tableid;
  271. }
  272. return $tableids;
  273. }
  274. function gettablefields($table) {
  275. static $tables = array();
  276. if(!isset($tables[$table])) {
  277. $tables[$table] = C::t('forum_post')->show_table_columns($table);
  278. }
  279. return $tables[$table];
  280. }
  281. function movedate($tids) {
  282. global $sourcesize, $tableid, $movesize, $targettableid, $hash, $tableindex, $threadtableids, $fieldstr, $fromtableid, $posttable_info;
  283. $fromtable = getposttable($fromtableid, true);
  284. C::t('forum_post')->move_table($targettableid, $fieldstr, $fromtable, $tids);
  285. if(DB::errno()) {
  286. C::t('forum_post')->delete_by_tid($targettableid, $tids);
  287. } else {
  288. foreach($threadtableids as $threadtableid) {
  289. $affected_rows = C::t('forum_thread')->update($tids, array('posttableid' => $targettableid), false, false, $threadtableid);
  290. if($affected_rows == count($tids)) {
  291. break;
  292. }
  293. }
  294. C::t('forum_post')->delete_by_tid($fromtableid, $tids);
  295. }
  296. $status = helper_dbtool::gettablestatus(getposttable($targettableid, true), false);
  297. $targetsize = $sourcesize + $movesize * 1048576;
  298. $nowdatasize = $targetsize - $status['Data_length'];
  299. if($status['Data_length'] >= $targetsize) {
  300. cpmsg('postsplit_done', 'action=postsplit&operation=optimize&tableid='.$fromtableid, 'form');
  301. }
  302. 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)));
  303. }
  304. ?>