PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/applications/appcenter/service/srv/helper/PwSystemHelper.php

https://github.com/cuijinquan/nextwind
PHP | 330 lines | 237 code | 19 blank | 74 comment | 65 complexity | 9c8e6d441d3261a229df2f67b6ee0e1f MD5 | raw file
  1. <?php
  2. Wind::import('APPCENTER:service.srv.helper.PwApplicationHelper');
  3. /**
  4. * 系统升级帮助类
  5. *
  6. * @author Shi Long <long.shi@alibaba-inc.com>
  7. * @copyright ©2003-2103 phpwind.com
  8. * @license http://www.windframework.com
  9. * @version $Id: PwSystemHelper.php 24585 2013-02-01 04:02:37Z jieyin $
  10. * @package wind
  11. */
  12. class PwSystemHelper {
  13. /**
  14. * 解析sql语句,并返回解析后的结果
  15. *
  16. * @param string $strSQL
  17. * @param string $charset
  18. * @param string $dbprefix
  19. * @return array($sqlStatement,$sqlOptions)
  20. */
  21. static public function sqlParser($strSQL, $charset, $dbprefix, $engine) {
  22. if (empty($strSQL)) return array();
  23. $dataSQL = array();
  24. $strSQL = str_replace(array("\r", "\n", "\r\n"), "\n", $strSQL);
  25. $arrSQL = explode("\n", $strSQL);
  26. $query = '';
  27. $i = $alter = 0;
  28. foreach ($arrSQL as $value) {
  29. $value = trim($value, " \t");
  30. if (!$value || substr($value, 0, 2) === '--') continue;
  31. $query .= $value;
  32. if (substr($query, -1) != ';') continue;
  33. $sql_key = strtoupper(substr($query, 0, strpos($query, ' ')));
  34. $query = preg_replace('/([ `]+)pw_/', '$1' . $dbprefix, $query);
  35. if ($sql_key == 'CREATE') {
  36. $query = preg_replace(
  37. array('/CREATE\s+TABLE(\s+IF\s+NOT\s+EXISTS)?/i', '/\)([\w\s=\x7f-\xff\']*);/i'),
  38. array(
  39. 'CREATE TABLE IF NOT EXISTS',
  40. ')ENGINE=' . $engine . ' DEFAULT CHARSET=' . $charset), $query);
  41. $dataSQL[$i][] = trim($query, ';');
  42. $alter = 0;
  43. } else if ($sql_key == 'DROP') {
  44. $dataSQL[$i][] = trim($query, ';');
  45. $alter = 0;
  46. } else if ($sql_key == 'ALTER') {
  47. $alter || ++$i;
  48. $dataSQL[$i][] = trim($query, ';');
  49. ++$i;
  50. $alter = 1;
  51. } elseif (in_array($sql_key, array('INSERT', 'REPLACE', 'UPDATE', 'DELETE'))) {
  52. $dataSQL[$i][] = trim($query, ';');
  53. $alter = 0;
  54. }
  55. $query = '';
  56. }
  57. return $dataSQL;
  58. }
  59. public static function alterIndex($value, $pdo) {
  60. $unique = 0;
  61. if ($value[3] == 'PRIMARY') {
  62. $add = $drop = 'PRIMARY KEY';
  63. } elseif ($value[3] == 'UNIQUE') {
  64. $add = "UNIQUE $value[1]";
  65. $drop = "INDEX $value[1]";
  66. } else {
  67. $add = $drop = "INDEX $value[1]";
  68. $unique = 1;
  69. }
  70. $indexkey = array();
  71. foreach ($pdo->query("SHOW KEYS FROM $value[0]")->fetchAll() as $rt) {
  72. $indexkey[$rt['Key_name']][$rt['Column_name']] = $unique;
  73. }
  74. if ($indexkey[$value[1]]) {
  75. if ($value[2]) {
  76. $ifdo = false;
  77. $column = explode(',', $value[2]);
  78. if (count($indexkey[$value[1]]) != count($column)) {
  79. $ifdo = true;
  80. } else {
  81. foreach ($column as $v) {
  82. if (!$indexkey[$value[1]][$v]) {
  83. $ifdo = true;
  84. break;
  85. }
  86. }
  87. }
  88. $ifdo && $pdo->execute("ALTER TABLE $value[0] DROP $drop,ADD $add ($value[2])");
  89. } elseif (empty($value[4]) || isset($indexkey[$value[1]][$value[4]])) {
  90. $pdo->execute("ALTER TABLE $value[0] DROP $drop");
  91. }
  92. } elseif ($value[2]) {
  93. $pdo->execute("ALTER TABLE $value[0] ADD $add ($value[2])");
  94. }
  95. }
  96. /**
  97. * 解析md5sum文件
  98. *
  99. * @param unknown_type $md5sum
  100. * @return multitype:multitype:
  101. */
  102. public static function resolveMd5($md5sum) {
  103. $md5List = array();
  104. foreach (explode("\n", $md5sum) as $v) {
  105. list($_k, $_v) = explode("\t", $v);
  106. if ($_k && $_v) {
  107. $md5List[$_v] = $_k;
  108. }
  109. }
  110. return $md5List;
  111. }
  112. public static function md5content($md5, $file) {
  113. return $md5 . "\t" . trim(str_replace(DIRECTORY_SEPARATOR, '/', $file), '/') . "\n";
  114. }
  115. /**
  116. * 计算sourcepath相对于targetpath的相对路径值
  117. *
  118. * @param unknown_type $sourcePath
  119. * @param unknown_type $targetPath
  120. * @return string
  121. */
  122. public static function resolveRelativePath($sourcePath, $targetPath) {
  123. list($sourcePath, $targetPath) = array(realpath($sourcePath), realpath($targetPath));
  124. $src_paths = explode(DIRECTORY_SEPARATOR, $sourcePath);
  125. $tgt_paths = explode(DIRECTORY_SEPARATOR, $targetPath);
  126. $src_count = count($src_paths);
  127. $tgt_count = count($tgt_paths);
  128. $relative_path = '';
  129. // 默认把不同点设在最后一个
  130. $break_point = $src_count;
  131. $i = 0;
  132. // 计算两个路径不相同的点,然后开始往上数..
  133. for ($i = 0; $i < $src_count; $i++) {
  134. if ($src_paths[$i] == $tgt_paths[$i]) continue;
  135. $relative_path .= '../';
  136. $break_point == $src_count && $break_point = $i;
  137. }
  138. $relative_path || $relative_path = './';
  139. // 往上..后,继续算目标路径的接下来的path
  140. for ($i = $break_point; $i < $tgt_count; $i++) {
  141. $relative_path .= $tgt_paths[$i] . '/';
  142. }
  143. return rtrim($relative_path, '/');
  144. }
  145. public static function alterField($value, $pdo) {
  146. // 检查表是否存在,以兼容论坛独立表某些表不存在的情况
  147. $ckTableIfExists = $pdo->query("SHOW TABLES LIKE '$value[0]'")->fetch();
  148. if (empty($ckTableIfExists)) continue;
  149. $rt = $pdo->query("SHOW COLUMNS FROM $value[0] LIKE '$value[1]'")->fetch();
  150. $lowersql = strtolower($value[2]);
  151. if ((strpos($lowersql, ' add ') !== false && $rt['Field'] != $value[1]) || (str_replace(
  152. array(' drop ', ' change '), '', $lowersql) != $lowersql && $rt['Field'] == $value[1])) {
  153. $pdo->execute($value[2]);
  154. }
  155. }
  156. /**
  157. * 使用socket下载
  158. *
  159. * @param unknown_type $url
  160. * @param unknown_type $file
  161. * @return multitype:boolean unknown
  162. */
  163. public static function downloadUseSocket($url, $file) {
  164. Wind::import('WIND:http.transfer.WindHttpSocket');
  165. $http = new WindHttpSocket($url);
  166. WindFolder::mkRecur(dirname($file));
  167. $data = $http->send();
  168. WindFile::write($file, $data);
  169. $http->close();
  170. return array(true, $file);
  171. }
  172. /**
  173. * 下载
  174. *
  175. * @param unknown_type $url
  176. * @param unknown_type $file
  177. * @param unknown_type $useSocket
  178. * @return Ambigous <multitype:boolean, multitype:boolean unknown_type >|multitype:boolean string |multitype:boolean unknown
  179. */
  180. public static function download($url, $file, $useSocket = false) {
  181. if ($useSocket) return self::downloadUseSocket($url, $file);
  182. Wind::import('WIND:http.transfer.WindHttpCurl');
  183. $http = new WindHttpCurl($url);
  184. WindFolder::mkRecur(dirname($file));
  185. $fp = fopen($file, "w");
  186. $opt = array(
  187. CURLOPT_FILE => $fp,
  188. CURLOPT_HEADER => 0,
  189. CURLOPT_SSL_VERIFYPEER => false,
  190. CURLOPT_SSL_VERIFYHOST => false);
  191. $http->send('GET', $opt);
  192. if ($e = $http->getError()) return array(false, $e);
  193. $http->close();
  194. fclose($fp);
  195. return array(true, $file);
  196. }
  197. /**
  198. * 根据升级列表校对md5
  199. *
  200. * 返回有更改的/无更改的/新增的
  201. */
  202. public static function validateMd5($fileList) {
  203. $change = $unchange = $new = array();
  204. foreach ($fileList as $f => $hash) {
  205. $file = ROOT_PATH . $f;
  206. if (!file_exists($file) || !$hash) {
  207. $new[] = $f;
  208. continue;
  209. }
  210. if (md5_file($file) != $hash)
  211. $change[] = $f;
  212. else
  213. $unchange[] = $f;
  214. }
  215. return array($change, $unchange, $new);
  216. }
  217. /**
  218. * 解压压缩包,将源文件解压至目标文件
  219. * 目前只支持zip文件的解压,返回解后包文件绝对路径地址
  220. *
  221. * @param string $source
  222. * @param string $target
  223. * @return string
  224. */
  225. static public function extract($source, $target) {
  226. Wind::import('APPCENTER:service.srv.helper.PwExtractZip');
  227. $zip = new PwExtractZip();
  228. if (!$data = $zip->extract($source)) return false;
  229. foreach ($data as $value) {
  230. $filename = $target . '/' . $value['filename'];
  231. WindFolder::mkRecur(dirname($filename));
  232. WindFile::write($filename, $value['data']);
  233. }
  234. return true;
  235. }
  236. /**
  237. * 检查升级文件目录可写
  238. *
  239. * @param unknown_type $fileList
  240. * @return multitype:boolean unknown |boolean
  241. */
  242. public static function checkFolder($fileList) {
  243. foreach ($fileList as $v => $hash) {
  244. $file = ROOT_PATH . $v;
  245. if (!self::checkWriteAble(file_exists($file) ? $file : dirname($file) . '/')) return array(
  246. false,
  247. $v);
  248. }
  249. return true;
  250. }
  251. public static function log($msg, $version, $start = false) {
  252. static $log;
  253. if (!$log) {
  254. $log = Wind::getRealDir('DATA:upgrade.log', true) . '/' . $version . '.log';
  255. WindFolder::mkRecur(dirname($log));
  256. }
  257. $status = $start ? WindFile::READWRITE : WindFile::APPEND_WRITEREAD;
  258. WindFile::write($log, "\r\n" . date('Y-m-d H:i') . ' ' . $msg, $status);
  259. }
  260. /**
  261. * 检查目录可写
  262. *
  263. * @param string $pathfile
  264. * @return boolean
  265. */
  266. public static function checkWriteAble($pathfile) {
  267. if (!$pathfile) return false;
  268. $isDir = substr($pathfile, -1) == '/' ? true : false;
  269. if ($isDir) {
  270. if (is_dir($pathfile)) {
  271. mt_srand((double) microtime() * 1000000);
  272. $pathfile = $pathfile . 'pw_' . uniqid(mt_rand()) . '.tmp';
  273. } else {
  274. return self::checkWriteAble(dirname($pathfile) . '/');
  275. }
  276. }
  277. $exist = file_exists($pathfile);
  278. @chmod($pathfile, 0777);
  279. $fp = @fopen($pathfile, 'ab');
  280. if ($fp === false) return false;
  281. fclose($fp);
  282. $exist || @unlink($pathfile);
  283. return true;
  284. }
  285. public static function relative($relativePath) {
  286. $pattern = '/\w+\/\.\.\/?/';
  287. $pattern = '/\w+' . preg_quote(DIRECTORY_SEPARATOR, '/') . '\.\.' . preg_quote(
  288. DIRECTORY_SEPARATOR, '/') . '?/';
  289. while (preg_match($pattern, $relativePath)) {
  290. $relativePath = preg_replace($pattern, '', $relativePath);
  291. }
  292. return $relativePath;
  293. }
  294. public static function replaceStr($str, $search, $replace, $count, $nums) {
  295. $strarr = explode($search, $str);
  296. $replacestr = '';
  297. foreach ($strarr as $key => $value) {
  298. if ($key == $count) {
  299. $replacestr .= $value;
  300. } else {
  301. if (in_array(($key + 1), $nums)) {
  302. $replacestr .= $value . $replace;
  303. } else {
  304. $replacestr .= $value . $search;
  305. }
  306. }
  307. }
  308. return $replacestr;
  309. }
  310. }
  311. ?>