zen.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <?php
  2. /**
  3. * The zen file of install module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  6. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Yuting Wang<wangyuting@easycorp.ltd>
  8. * @package install
  9. * @link https://www.zentao.net
  10. */
  11. class installZen extends install
  12. {
  13. /**
  14. * 获取当前PHP版本。
  15. * get php version.
  16. *
  17. * @access protected
  18. * @return string
  19. */
  20. protected function getPHPVersion()
  21. {
  22. return PHP_VERSION;
  23. }
  24. /**
  25. * 获取tmp的目录信息。
  26. * Get tempRoot info.
  27. *
  28. * @access protected
  29. * @return array
  30. */
  31. protected function getTmpRoot()
  32. {
  33. $result['path'] = $this->app->getTmpRoot();
  34. $result['exists'] = is_dir($result['path']);
  35. $result['writable'] = is_writable($result['path']);
  36. return $result;
  37. }
  38. /**
  39. * 获取session的存储目录信息。
  40. * Get session save path.
  41. *
  42. * @access protected
  43. * @return array
  44. */
  45. protected function getSessionSavePath()
  46. {
  47. $result['path'] = preg_replace("/\d;/", '', session_save_path());
  48. $result['exists'] = is_dir($result['path']);
  49. $result['writable'] = is_writable($result['path']);
  50. return $result;
  51. }
  52. /**
  53. * 获取附件存储的目录信息。
  54. * Get data root.
  55. *
  56. * @access protected
  57. * @return array
  58. */
  59. protected function getDataRoot()
  60. {
  61. $result['path'] = $this->app->getAppRoot() . 'www' . DS . 'data';
  62. $result['exists'] = is_dir($result['path']);
  63. $result['writable']= is_writable($result['path']);
  64. return $result;
  65. }
  66. /**
  67. * 检查PHP版本是否大于5.2.0。
  68. * Check php version.
  69. *
  70. * @access protected
  71. * @return string ok|fail
  72. */
  73. protected function checkPHPVersion()
  74. {
  75. return version_compare(PHP_VERSION, '5.2.0') >= 0 ? 'ok' : 'fail';
  76. }
  77. /**
  78. * 检查是否安装pdo扩展。
  79. * Check PDO.
  80. *
  81. * @access protected
  82. * @return string ok|fail
  83. */
  84. protected function checkPDO()
  85. {
  86. return extension_loaded('pdo') ? 'ok' : 'fail';
  87. }
  88. /**
  89. * 检查是否安装pdo_mysql扩展。
  90. * Check PDO::MySQL
  91. *
  92. * @access protected
  93. * @return string ok|fail
  94. */
  95. protected function checkPDOMySQL()
  96. {
  97. return extension_loaded('pdo_mysql') ? 'ok' : 'fail';
  98. }
  99. /**
  100. * 检查是否安装了json扩展。
  101. * Check json extension.
  102. *
  103. * @access protected
  104. * @return string ok|fail
  105. */
  106. protected function checkJSON()
  107. {
  108. return extension_loaded('json') ? 'ok' : 'fail';
  109. }
  110. /**
  111. * 检查是否安装了openssl扩展。
  112. * Check openssl extension.
  113. *
  114. * @access protected
  115. * @return string ok|fail
  116. */
  117. protected function checkOpenssl()
  118. {
  119. return extension_loaded('openssl') ? 'ok' : 'fail';
  120. }
  121. /**
  122. * 检查是否安装了mbstring扩展。
  123. * Check mbstring extension.
  124. *
  125. * @access protected
  126. * @return string ok|fail
  127. */
  128. protected function checkMBstring()
  129. {
  130. return extension_loaded('mbstring') ? 'ok' : 'fail';
  131. }
  132. /**
  133. * 检查是否安装了zlib扩展。
  134. * Check zlib extension.
  135. *
  136. * @access protected
  137. * @return string ok|fail
  138. */
  139. protected function checkZlib()
  140. {
  141. return extension_loaded('zlib') ? 'ok' : 'fail';
  142. }
  143. /**
  144. * 检查是否安装了curl扩展。
  145. * Check curl extension.
  146. *
  147. * @access protected
  148. * @return string ok|fail
  149. */
  150. protected function checkCURL()
  151. {
  152. return extension_loaded('curl') ? 'ok' : 'fail';
  153. }
  154. /**
  155. * 检查是否安装了filter扩展。
  156. * Check filter extension.
  157. *
  158. * @access protected
  159. * @return string ok|fail
  160. */
  161. protected function checkFilter()
  162. {
  163. return extension_loaded('filter') ? 'ok' : 'fail';
  164. }
  165. /**
  166. * 检查是否安装了iconv扩展。
  167. * Check iconv extension.
  168. *
  169. * @access protected
  170. * @return string ok|fail
  171. */
  172. protected function checkIconv()
  173. {
  174. return extension_loaded('iconv') ? 'ok' : 'fail';
  175. }
  176. /**
  177. * 检查tmp目录的完整性和可写性。
  178. * Check tmpRoot.
  179. *
  180. * @access protected
  181. * @return string ok|fail
  182. */
  183. protected function checkTmpRoot()
  184. {
  185. $tmpRoot = $this->app->getTmpRoot();
  186. return is_dir($tmpRoot) && is_writable($tmpRoot) ? 'ok' : 'fail';
  187. }
  188. /**
  189. * 检查session存储目录的完整性和可写性质。
  190. * Check session save path.
  191. *
  192. * @access protected
  193. * @return string ok|fail
  194. */
  195. protected function checkSessionSavePath()
  196. {
  197. $sessionSavePath = preg_replace("/\d;/", '', session_save_path());
  198. if(!is_dir($sessionSavePath) || !is_writable($sessionSavePath)) return 'fail';
  199. /* Test session path again. */
  200. file_put_contents($sessionSavePath . '/zentaotest', 'zentao');
  201. $sessionContent = file_get_contents($sessionSavePath . '/zentaotest');
  202. if($sessionContent == 'zentao')
  203. {
  204. unlink($sessionSavePath . '/zentaotest');
  205. return 'ok';
  206. }
  207. return 'fail';
  208. }
  209. /**
  210. * 检查附件存储目录的完整性和可写性质。
  211. * Check the data root.
  212. *
  213. * @access protected
  214. * @return string ok|fail
  215. */
  216. protected function checkDataRoot()
  217. {
  218. $dataRoot = $this->app->getAppRoot() . 'www' . DS . 'data';
  219. return is_dir($dataRoot) && is_writable($dataRoot) ? 'ok' : 'fail';
  220. }
  221. /**
  222. * 检查数据库配置信息的正确性。
  223. * Check config ok or not.
  224. *
  225. * @param object $data
  226. * @access protected
  227. * @return object
  228. */
  229. protected function checkConfig($data)
  230. {
  231. $return = new stdclass();
  232. $return->result = 'ok';
  233. /* Connect to database. */
  234. $this->setDBParam($data);
  235. $this->install->dbh = $this->install->connectDB();
  236. if(strpos($data->dbName, '.') !== false)
  237. {
  238. /* 如果数据库名字带有.字符的话,则提示错误信息。 */
  239. $return->result = 'fail';
  240. $return->error = $this->lang->install->errorDBName;
  241. return $return;
  242. }
  243. if(!is_object($this->install->dbh))
  244. {
  245. /* 没有成功连接数据库的话,则提示错误信息。 */
  246. $return->result = 'fail';
  247. $return->error = $this->lang->install->errorConnectDB . $this->install->dbh;
  248. return $return;
  249. }
  250. /* 检查数据库用户是否缺少权限。 */
  251. $missingPrivs = $this->install->dbh->checkUserPriv();
  252. if($missingPrivs)
  253. {
  254. $missingPrivs = $this->lang->install->errorDBUserPriv . '<code>' . $missingPrivs . '</code>';
  255. return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.alert({icon: 'icon-exclamation-sign', size: '600', iconClass: 'text-4xl text-warning', message: {html:'" . str_replace("'", '"', $missingPrivs) . "'}})"));
  256. }
  257. /* Get database version. */
  258. $version = $this->install->getDatabaseVersion();
  259. /* If database no exits, try create it. */
  260. if(!$this->install->dbh->dbExists())
  261. {
  262. if(!$this->install->dbh->createDB($version))
  263. {
  264. /* 如果创建数据库失败的话,则提示错误信息。 */
  265. $return->result = 'fail';
  266. $return->error = $this->lang->install->errorCreateDB;
  267. return $return;
  268. }
  269. }
  270. elseif($this->install->dbh->tableExist(TABLE_ACL) && empty($data->clearDB))
  271. {
  272. /* 如果已经存在config表,并且用户没有勾选清空旧数据库选项的话,则提示错误信息。 */
  273. $return->result = 'fail';
  274. $return->error = $this->lang->install->errorTableExists;
  275. return $return;
  276. }
  277. return $return;
  278. }
  279. /**
  280. * DevOps平台版将配置信息写入my.php。
  281. * Save config file when inQuickon is true.
  282. *
  283. * @access protected
  284. * @return bool
  285. */
  286. protected function saveConfigFile()
  287. {
  288. $configRoot = $this->app->getConfigRoot();
  289. $myConfigFile = $configRoot . 'my.php';
  290. if(file_exists($myConfigFile) && trim(file_get_contents($myConfigFile))) return false;
  291. /* Set the session save path when the session save path is null. */
  292. $customSession = $this->setSessionPath();
  293. $configContent = <<<EOT
  294. <?php
  295. \$config->installed = getEnvData('ZT_INSTALLED', true, 'bool');
  296. \$config->debug = getEnvData('ZT_DEBUG', 0, 'int');
  297. \$config->requestType = getEnvData('ZT_REQUEST_TYPE');
  298. \$config->timezone = getEnvData('ZT_TIMEZONE', 'Asia/Shanghai');
  299. \$config->db->driver = getEnvData('ZT_DB_DRIVER', 'mysql');
  300. \$config->db->host = getEnvData('ZT_DB_HOST');
  301. \$config->db->port = getEnvData('ZT_DB_PORT');
  302. \$config->db->name = getEnvData('ZT_DB_NAME');
  303. \$config->db->user = getEnvData('ZT_DB_USER');
  304. \$config->db->encoding = getEnvData('ZT_DB_ENCODING', 'UTF8');
  305. \$config->db->password = getEnvData('ZT_DB_PASSWORD');
  306. \$config->db->prefix = getEnvData('ZT_DB_PREFIX');
  307. \$config->webRoot = getWebRoot();
  308. \$config->default->lang = getEnvData('ZT_DEFAULT_LANG', 'zh-cn');
  309. \$hasSlaveDB = (string)getEnvData('ENABLE_DB_SLAVE');
  310. if(\$hasSlaveDB && \$hasSlaveDB != 'false')
  311. {
  312. \$slaveDB = new stdclass();
  313. \$slaveDB->host = getEnvData('ZT_SLAVE_DB_HOST');
  314. \$slaveDB->port = getEnvData('ZT_SLAVE_DB_PORT');
  315. \$slaveDB->name = getEnvData('ZT_SLAVE_DB_NAME');
  316. \$slaveDB->user = getEnvData('ZT_SLAVE_DB_USER');
  317. \$slaveDB->password = getEnvData('ZT_SLAVE_DB_PASSWORD');
  318. \$slaveDB->driver = getEnvData('ZT_DB_DRIVER');
  319. \$slaveDB->encoding = getEnvData('ZT_DB_ENCODING');
  320. \$slaveDB->prefix = getEnvData('ZT_DB_PREFIX');
  321. \$config->slaveDBList = array(\$slaveDB);
  322. }
  323. EOT;
  324. if($customSession) $configContent .= "\n\$config->customSession = true;";
  325. if(is_writable($configRoot)) @file_put_contents($myConfigFile, $configContent);
  326. $this->config->installed = true;
  327. return true;
  328. }
  329. /**
  330. * 写入数据库配置信息。
  331. * Set database params.
  332. *
  333. * @param object $data
  334. * @access private
  335. * @return bool
  336. */
  337. private function setDBParam($data)
  338. {
  339. $this->config->db->driver = $data->dbDriver;
  340. if($this->config->inQuickon)
  341. {
  342. $this->config->db->host = getenv('ZT_MYSQL_HOST');
  343. $this->config->db->user = getenv('ZT_MYSQL_USER');
  344. $this->config->db->encoding = 'UTF8';
  345. $this->config->db->password = getenv('ZT_MYSQL_PASSWORD');
  346. $this->config->db->port = getenv('ZT_MYSQL_PORT');
  347. }
  348. else
  349. {
  350. $this->config->db->host = $data->dbHost;
  351. $this->config->db->user = $data->dbUser;
  352. $this->config->db->encoding = $data->dbEncoding;
  353. $this->config->db->password = $data->dbPassword;
  354. $this->config->db->port = $data->dbPort;
  355. }
  356. $this->config->db->name = $data->dbName;
  357. $this->config->db->prefix = $data->dbPrefix;
  358. file_put_contents($this->install->buildDBLogFile('config'), json_encode(array('db' => $this->config->db, 'post' => $data)));
  359. return true;
  360. }
  361. /**
  362. * DevOps平台版设置session path。
  363. * Set session save path.
  364. *
  365. * @access private
  366. * @return bool
  367. */
  368. private function setSessionPath()
  369. {
  370. $customSession = false;
  371. $checkSession = ini_get('session.save_handler') == 'files';
  372. if($checkSession)
  373. {
  374. if(!session_save_path())
  375. {
  376. /* Restart the session because the session save path is null when start the session last time. */
  377. session_write_close();
  378. $tmpRootInfo = $this->getTmpRoot();
  379. $sessionSavePath = $tmpRootInfo['path'] . 'session';
  380. if(!is_dir($sessionSavePath)) mkdir($sessionSavePath, 0777, true);
  381. session_save_path($sessionSavePath);
  382. $customSession = true;
  383. $sessionResult = $this->checkSessionSavePath();
  384. if($sessionResult == 'fail') chmod($sessionSavePath, 0777);
  385. session_start();
  386. $this->session->set('installing', true);
  387. }
  388. }
  389. $_SESSION['installing'] = true;
  390. return $customSession;
  391. }
  392. /**
  393. * 处理安装应用下拉选择的数据。
  394. * Process application options.
  395. *
  396. * @param object $components
  397. * @param object $cloudSolution
  398. * @access protected
  399. * @return object
  400. */
  401. protected function processComponents($components, $cloudSolution)
  402. {
  403. foreach($components->category as $key => &$item)
  404. {
  405. if($item->name === 'pms')
  406. {
  407. unset($components->category[$key]);
  408. continue;
  409. }
  410. if(in_array($item->name, array('analysis', 'artifact'))) array_unshift($item->choices, (object)array('name' => $this->lang->install->solution->skipInstall, 'version' => ''));
  411. $item->schemaChoices = array();
  412. foreach($item->choices as $cloudApp)
  413. {
  414. $appInfo = zget($cloudSolution->apps, $cloudApp->name, array());
  415. $item->schemaChoices[$cloudApp->name] = zget($appInfo, 'alias', $cloudApp->name);
  416. }
  417. }
  418. return $components;
  419. }
  420. }