diff --git a/config/zentaopms.php b/config/zentaopms.php index 21556a4d39..97c9b578c8 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -199,6 +199,7 @@ $config->openMethods[] = 'misc.ping'; $config->openMethods[] = 'misc.captcha'; $config->openMethods[] = 'misc.features'; $config->openMethods[] = 'misc.getremind'; +$config->openMethods[] = 'misc.checknetconnect'; $config->openMethods[] = 'sso.login'; $config->openMethods[] = 'sso.logout'; $config->openMethods[] = 'sso.bind'; diff --git a/module/misc/control.php b/module/misc/control.php index e5652f241c..55dcf81c89 100644 --- a/module/misc/control.php +++ b/module/misc/control.php @@ -210,12 +210,13 @@ class misc extends control * Check net connect. * * @access public - * @return string + * @return void */ - public function checkNetConnect(): string + public function checkNetConnect(): void { $this->app->loadConfig('extension'); - $check = @fopen(dirname($this->config->extension->apiRoot), "r"); + $context = stream_context_create(array("ssl" => array("verify_peer" => false, "verify_peer_name" => false))); + $check = @fopen(dirname($this->config->extension->apiRoot), "r", false, $context); print($check ? 'success' : 'fail'); } diff --git a/module/upgrade/control.php b/module/upgrade/control.php index 8e5d181a61..1a0cd8356c 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -847,6 +847,38 @@ class upgrade extends control return print(json_encode(array('log' => str_replace("\n", "
", $log) . ($log ? '
' : ''), 'progress' => $progress, 'offset' => $offset + strlen($log)))); } + /** + * Ajax get fix consistency logs. + * + * @param int $offset + * @access public + * @return void + */ + public function ajaxGetFixLogs($offset = 0) + { + $logFile = $this->upgrade->getConsistencyLogFile(); + $lines = !file_exists($logFile) ? array() : file($logFile); + + $log = array_slice($lines, $offset); + $finished = ($log and end($log) == 'Finished') ? true : false; + + return print(json_encode(array('log' => implode("
", $log), 'finished' => $finished, 'offset' => count($lines)))); + } + + /** + * Ajax fix for consistency. + * + * @param string $version + * @access public + * @return void + */ + public function ajaxFixConsistency($version) + { + set_time_limit(0); + session_write_close(); + $this->upgrade->fixConsistency($version); + } + /** * Get the project of the program it belongs to. * @@ -900,8 +932,14 @@ class upgrade extends control $alterSQL = $this->upgrade->checkConsistency($this->config->version); if(!empty($alterSQL)) { + $logFile = $this->upgrade->getConsistencyLogFile(); + $hasError = $this->upgrade->hasConsistencyError(); + if(file_exists($logFile)) unlink($logFile); + $this->view->title = $this->lang->upgrade->consistency; + $this->view->hasError = $hasError; $this->view->alterSQL = $alterSQL; + $this->view->version = $this->config->version; return $this->display('upgrade', 'consistency'); } @@ -953,9 +991,11 @@ class upgrade extends control */ public function consistency($netConnect = true) { - set_time_limit(0); + $logFile = $this->upgrade->getConsistencyLogFile(); + $hasError = $this->upgrade->hasConsistencyError(); + if(file_exists($logFile)) unlink($logFile); + $alterSQL = $this->upgrade->checkConsistency(); - $alterSQL = str_replace('ENGINE=MyISAM', 'ENGINE=InnoDB', $alterSQL); if(empty($alterSQL)) { if(!$netConnect) $this->locate(inlink('selectVersion')); @@ -963,7 +1003,9 @@ class upgrade extends control } $this->view->title = $this->lang->upgrade->consistency; + $this->view->hasError = $hasError; $this->view->alterSQL = $alterSQL; + $this->view->version = $this->config->installedVersion; $this->display(); } diff --git a/module/upgrade/js/backup.ui.js b/module/upgrade/js/backup.ui.js index 43f954392b..3e59952cd5 100644 --- a/module/upgrade/js/backup.ui.js +++ b/module/upgrade/js/backup.ui.js @@ -1,17 +1,14 @@ -$(function() +$.ajax( { - $.ajax( + url: $.createLink('misc', 'checkNetConnect'), + timeout: 3000, + success: function(data) { - url: $.createLink('misc', 'checkNetConnect'), - timeout: 3000, - success: function(data) - { - if(data == 'fail') $('.btn.primary.disabled').attr('onclick', "self.location.href=\"" + $.createLink('upgrade', 'consistency', "netConnect=0") + "\""); - $('.btn.primary.disabled').removeClass('disabled'); - }, - error: function(XMLHttpRequest, textStatus) - { - $('.btn.primary.disabled').attr('onclick', "self.location.href=\"" + $.createLink('upgrade', 'consistency', "netConnect=0") + "\"").removeClass('disabled'); - } - }); + if(data == 'fail') $('.btn.primary.disabled').attr('onclick', "self.location.href=\"" + $.createLink('upgrade', 'consistency', "netConnect=0") + "\""); + $('.btn.primary.disabled').removeClass('disabled'); + }, + error: function(XMLHttpRequest, textStatus) + { + $('.btn.primary.disabled').attr('onclick', "self.location.href=\"" + $.createLink('upgrade', 'consistency', "netConnect=0") + "\"").removeClass('disabled'); + } }); diff --git a/module/upgrade/js/consistency.ui.js b/module/upgrade/js/consistency.ui.js new file mode 100644 index 0000000000..33c9645c0d --- /dev/null +++ b/module/upgrade/js/consistency.ui.js @@ -0,0 +1,29 @@ +function updateProgressInterval() +{ + $.get($.createLink('upgrade', 'ajaxFixConsistency', 'version=' + version)); + showLogs(0); +} + +function showLogs(logOffset) +{ + var url = $.createLink('upgrade', 'ajaxGetFixLogs', 'offset=' + logOffset); + $.getJSON(url, function(result) + { + logOffset = result.offset; + + if(result.log) $('#logBox').append(result.log); + + let element = document.getElementById('logBox'); + element.scrollTop = element.scrollHeight; + + if(result.finished) + { + loadCurrentPage(); + return; + } + + showLogs(logOffset); + }) +} + +if(execFixSQL) updateProgressInterval() diff --git a/module/upgrade/lang/zh-cn.php b/module/upgrade/lang/zh-cn.php index 3b6de84b7d..5f8dbbe275 100644 --- a/module/upgrade/lang/zh-cn.php +++ b/module/upgrade/lang/zh-cn.php @@ -68,7 +68,8 @@ $lang->upgrade->sureExecute = '确认执行'; $lang->upgrade->upgradingTips = '正在升级中,请耐心等待,切勿刷新页面、断电、关机!'; $lang->upgrade->forbiddenExt = '以下插件与新版本不兼容,已经自动禁用:'; $lang->upgrade->updateFile = '需要更新附件信息。'; -$lang->upgrade->noticeSQL = '检查到你的数据库跟标准不一致,尝试修复失败。请执行以下SQL语句,再刷新页面检查。'; +$lang->upgrade->showSQLLog = '检查到你的数据库跟标准不一致,正在尝试修复。以下是修复SQL语句。'; +$lang->upgrade->noticeErrSQL = '检查到你的数据库跟标准不一致,尝试修复失败。请手动执行以下SQL语句,再刷新页面检查。'; $lang->upgrade->afterDeleted = '请执行上面命令删除文件, 删除后刷新!'; $lang->upgrade->afterExec = '请根据以上报错信息手动修改数据库,修改后刷新!'; $lang->upgrade->mergeProgram = '数据迁移'; diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 55d6ba6eef..0780702710 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -997,29 +997,90 @@ class upgradeModel extends model } elseif($line != $fields[$field]) { + $stdConfigs = explode(' ', $line); + $dbConfigs = explode(' ', $fields[$field]); + + if($stdConfigs[1] != $dbConfigs[1]) + { + $stdType = $stdConfigs[1]; + $dbType = $dbConfigs[1]; + $stdLength = 0; + $dbLength = 0; + + preg_match_all('/^(\w+)(\((\d+)\))?$/', $stdConfigs[1], $stdOutput); + if(!empty($stdOutput[1][0])) $stdType = $stdOutput[1][0]; + if(!empty($stdOutput[3][0])) $stdLength = $stdOutput[3][0]; + + preg_match_all('/^(\w+)(\((\d+)\))?$/', $dbConfigs[1], $dbOutput); + if(!empty($dbOutput[1][0])) $dbType = $dbOutput[1][0]; + if(!empty($dbOutput[3][0])) $dbLength = $dbOutput[3][0]; + + $stdIsInt = stripos($stdType, 'int') !== false; + $stdIsVarchar = stripos($stdType, 'varchar') !== false; + $stdIsText = stripos($stdType, 'text') !== false; + $dbIsInt = stripos($dbType, 'int') !== false; + $dbIsVarchar = stripos($dbType, 'varchar') !== false; + $dbIsText = stripos($dbType, 'text') !== false; + + if($dbLength > $stdLength) $stdConfigs[1] = $dbConfigs[1]; + if($stdIsInt && $dbIsText) $stdConfigs[1] = $dbConfigs[1]; + if($stdIsVarchar && $dbIsText) $stdConfigs[1] = $dbConfigs[1]; + if($stdIsText && $dbIsText) + { + if($stdType == 'text' && in_array($dbType, array('mediumtext', 'longtext'))) $stdConfigs[1] = $dbConfigs[1]; + if($stdType == 'mediumtext' && $dbType == 'longtext') $stdConfigs[1] = $dbConfigs[1]; + } + if(stripos($stdConfigs[1], 'int') === false && $stdConfigs[2] == 'unsigned') unset($stdConfigs[2]); + $line = implode(' ', $stdConfigs); + if($line == $fields[$field]) continue; + } + $execSQL = "ALTER TABLE `$table` CHANGE $field $line"; } if($execSQL) { - if(stripos($execSQL, 'auto_increment') !== false) $execSQL .= ' primary key'; + if(stripos($execSQL, 'auto_increment') !== false) $execSQL .= ' FIRST'; $alterSQL[] = "$execSQL"; } } } - if(count($alterSQL) > 100) return implode(";\n", $alterSQL); - foreach($alterSQL as $i => $execSQL) + return implode(";\n", $alterSQL); + } + + /** + * Exec fix sql for consistency. + * + * @param string $version + * @access public + * @return void + */ + public function fixConsistency($version) + { + $logFile = $this->getConsistencyLogFile(); + if(file_exists($logFile)) unlink($logFile); + + $hasError = false; + $fixSqls = $this->checkConsistency($version); + if($fixSqls) $fixSqls = "SET @@sql_mode= '';" . $fixSqls; + foreach(explode(';', $fixSqls) as $fixSQL) { + file_put_contents($logFile, $fixSQL, FILE_APPEND); try { - $this->dbh->exec($execSQL); - unset($alterSQL[$i]); + $this->dbh->exec($fixSQL); + } + catch(PDOException $e) + { + $hasError = true; + file_put_contents($logFile, $e->getMessage() . "\n", FILE_APPEND); } - catch(PDOException $e){} } - return implode(";\n", $alterSQL); + $finishTag = "\nFinished"; + if($hasError) $finishTag = "\nHasError" . $finishTag; + file_put_contents($logFile, $finishTag, FILE_APPEND); } /** @@ -2751,6 +2812,17 @@ class upgradeModel extends model return $errors; } + /** + * Get upgrade log file. + * + * @access public + * @return string + */ + public function getConsistencyLogFile() + { + return $this->app->getTmpRoot() . 'log/consistency.' . date('Ymd') . '.log.php'; + } + /** * Get upgrade log file. * @@ -9304,4 +9376,23 @@ class upgradeModel extends model { touch($this->app->getCacheRoot() . 'restartcron'); } + + public function hasConsistencyError() + { + $logFile = $this->getConsistencyLogFile(); + if(!file_exists($logFile)) return false; + + $lastTwoLines = array(0 =>'', 1 => ''); + + $fh = fopen($logFile, 'r'); + while(!feof($fh)) + { + $lastTwoLines[0] = $lastTwoLines[1]; + $lastTwoLines[1] = fgets($fh); + } + fclose($fh); + + if(trim($lastTwoLines[0]) == 'HasError') return true; + return false; + } } diff --git a/module/upgrade/ui/consistency.html.php b/module/upgrade/ui/consistency.html.php index c416cb138b..aa163cd482 100644 --- a/module/upgrade/ui/consistency.html.php +++ b/module/upgrade/ui/consistency.html.php @@ -12,7 +12,9 @@ namespace zin; set::zui(true); -$alterSQL = "SET @@sql_mode= '';\n{$alterSQL}"; +jsVar('version', $version); +jsVar('execFixSQL', !empty($alterSQL) && !$hasError); + div ( setID('main'), @@ -31,13 +33,13 @@ div div ( setClass('article-h3 mb-2'), - $lang->upgrade->noticeSQL + $hasError ? $lang->upgrade->noticeErrSQL : $lang->upgrade->showSQLLog ), - h::textarea + div ( - set::style(array('height' => '200px', 'width' => '100%')), - set::readonly(true), - html($alterSQL) + set::style(array('height' => '200px', 'width' => '100%', 'overflow' => 'auto')), + set::id('logBox'), + $hasError ? html($alterSQL) : null ) ), div