464 lines
14 KiB
PHP
464 lines
14 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
/**
|
||
* The zen file of install module of ZenTaoPMS.
|
||
*
|
||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||
* @author Yuting Wang<wangyuting@easycorp.ltd>
|
||
* @package install
|
||
* @link https://www.zentao.net
|
||
*/
|
||
class installZen extends install
|
||
{
|
||
/**
|
||
* 获取当前PHP版本。
|
||
* get php version.
|
||
*
|
||
* @access protected
|
||
* @return string
|
||
*/
|
||
protected function getPHPVersion(): string
|
||
{
|
||
return PHP_VERSION;
|
||
}
|
||
|
||
/**
|
||
* 获取tmp的目录信息。
|
||
* Get tempRoot info.
|
||
*
|
||
* @access protected
|
||
* @return array
|
||
*/
|
||
protected function getTmpRoot(): array
|
||
{
|
||
$result['path'] = $this->app->getTmpRoot();
|
||
$result['exists'] = is_dir($result['path']);
|
||
$result['writable'] = is_writable($result['path']);
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 获取session的存储目录信息。
|
||
* Get session save path.
|
||
*
|
||
* @access protected
|
||
* @return array
|
||
*/
|
||
protected function getSessionSavePath(): array
|
||
{
|
||
$result['path'] = preg_replace("/\d;/", '', session_save_path());
|
||
$result['exists'] = is_dir($result['path']);
|
||
$result['writable'] = is_writable($result['path']);
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 获取附件存储的目录信息。
|
||
* Get data root.
|
||
*
|
||
* @access protected
|
||
* @return array
|
||
*/
|
||
protected function getDataRoot(): array
|
||
{
|
||
$result['path'] = $this->app->getAppRoot() . 'www' . DS . 'data';
|
||
$result['exists'] = is_dir($result['path']);
|
||
$result['writable']= is_writable($result['path']);
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 检查PHP版本是否大于5.2.0。
|
||
* Check php version.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkPHPVersion(): string
|
||
{
|
||
return version_compare(PHP_VERSION, '5.2.0') >= 0 ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装pdo扩展。
|
||
* Check PDO.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkPDO(): string
|
||
{
|
||
return extension_loaded('pdo') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装pdo_mysql扩展。
|
||
* Check PDO::MySQL
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkPDOMySQL(): string
|
||
{
|
||
return extension_loaded('pdo_mysql') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了json扩展。
|
||
* Check json extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkJSON(): string
|
||
{
|
||
return extension_loaded('json') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了openssl扩展。
|
||
* Check openssl extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkOpenssl(): string
|
||
{
|
||
return extension_loaded('openssl') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了mbstring扩展。
|
||
* Check mbstring extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkMBstring(): string
|
||
{
|
||
return extension_loaded('mbstring') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了zlib扩展。
|
||
* Check zlib extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkZlib(): string
|
||
{
|
||
return extension_loaded('zlib') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了curl扩展。
|
||
* Check curl extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkCURL(): string
|
||
{
|
||
return extension_loaded('curl') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了filter扩展。
|
||
* Check filter extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkFilter(): string
|
||
{
|
||
return extension_loaded('filter') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查是否安装了iconv扩展。
|
||
* Check iconv extension.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkIconv(): string
|
||
{
|
||
return extension_loaded('iconv') ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查tmp目录的完整性和可写性。
|
||
* Check tmpRoot.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkTmpRoot(): string
|
||
{
|
||
$tmpRoot = $this->app->getTmpRoot();
|
||
return is_dir($tmpRoot) && is_writable($tmpRoot) ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查session存储目录的完整性和可写性质。
|
||
* Check session save path.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkSessionSavePath(): string
|
||
{
|
||
$sessionSavePath = preg_replace("/\d;/", '', session_save_path());
|
||
if(!is_dir($sessionSavePath) || !is_writable($sessionSavePath)) return 'fail';
|
||
|
||
/* Test session path again. */
|
||
file_put_contents($sessionSavePath . '/zentaotest', 'zentao');
|
||
$sessionContent = file_get_contents($sessionSavePath . '/zentaotest');
|
||
if($sessionContent == 'zentao')
|
||
{
|
||
unlink($sessionSavePath . '/zentaotest');
|
||
return 'ok';
|
||
}
|
||
return 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查附件存储目录的完整性和可写性质。
|
||
* Check the data root.
|
||
*
|
||
* @access protected
|
||
* @return string ok|fail
|
||
*/
|
||
protected function checkDataRoot(): string
|
||
{
|
||
$dataRoot = $this->app->getAppRoot() . 'www' . DS . 'data';
|
||
return is_dir($dataRoot) && is_writable($dataRoot) ? 'ok' : 'fail';
|
||
}
|
||
|
||
/**
|
||
* 检查数据库配置信息的正确性。
|
||
* Check config ok or not.
|
||
*
|
||
* @param object $data
|
||
* @access protected
|
||
* @return object
|
||
*/
|
||
protected function checkConfig(object $data): object
|
||
{
|
||
$return = new stdclass();
|
||
$return->result = 'ok';
|
||
|
||
/* Connect to database. */
|
||
$this->setDBParam($data);
|
||
$this->install->dbh = $this->install->connectDB();
|
||
if(strpos($data->dbName, '.') !== false)
|
||
{
|
||
/* 如果数据库名字带有.字符的话,则提示错误信息。 */
|
||
$return->result = 'fail';
|
||
$return->error = $this->lang->install->errorDBName;
|
||
return $return;
|
||
}
|
||
if(!is_object($this->install->dbh))
|
||
{
|
||
/* 没有成功连接数据库的话,则提示错误信息。 */
|
||
$return->result = 'fail';
|
||
$return->error = $this->lang->install->errorConnectDB . $this->install->dbh;
|
||
return $return;
|
||
}
|
||
|
||
/* 检查数据库用户是否缺少权限。 */
|
||
$missingPrivs = $this->install->dbh->checkUserPriv();
|
||
if($missingPrivs)
|
||
{
|
||
$missingPrivs = $this->lang->install->errorDBUserPriv . '<code>' . $missingPrivs . '</code>';
|
||
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) . "'}})"));
|
||
}
|
||
|
||
/* Get database version. */
|
||
$version = $this->install->getDatabaseVersion();
|
||
|
||
/* If database no exits, try create it. */
|
||
if(!$this->install->dbh->dbExists())
|
||
{
|
||
if(!$this->install->dbh->createDB($version))
|
||
{
|
||
/* 如果创建数据库失败的话,则提示错误信息。 */
|
||
$return->result = 'fail';
|
||
$return->error = $this->lang->install->errorCreateDB;
|
||
return $return;
|
||
}
|
||
}
|
||
elseif($this->install->dbh->tableExist(TABLE_ACL) && empty($data->clearDB))
|
||
{
|
||
/* 如果已经存在config表,并且用户没有勾选清空旧数据库选项的话,则提示错误信息。 */
|
||
$return->result = 'fail';
|
||
$return->error = $this->lang->install->errorTableExists;
|
||
return $return;
|
||
}
|
||
|
||
return $return;
|
||
}
|
||
|
||
/**
|
||
* DevOps平台版将配置信息写入my.php。
|
||
* Save config file when inQuickon is true.
|
||
*
|
||
* @access protected
|
||
* @return bool
|
||
*/
|
||
protected function saveConfigFile(): bool
|
||
{
|
||
$configRoot = $this->app->getConfigRoot();
|
||
$myConfigFile = $configRoot . 'my.php';
|
||
if(file_exists($myConfigFile) && trim(file_get_contents($myConfigFile))) return false;
|
||
|
||
/* Set the session save path when the session save path is null. */
|
||
$customSession = $this->setSessionPath();
|
||
$configContent = <<<EOT
|
||
<?php
|
||
\$config->installed = getEnvData('ZT_INSTALLED', true, 'bool');
|
||
\$config->debug = getEnvData('ZT_DEBUG', 0, 'int');
|
||
\$config->requestType = getEnvData('ZT_REQUEST_TYPE');
|
||
\$config->timezone = getEnvData('ZT_TIMEZONE', 'Asia/Shanghai');
|
||
\$config->db->driver = getEnvData('ZT_DB_DRIVER', 'mysql');
|
||
\$config->db->host = getEnvData('ZT_DB_HOST');
|
||
\$config->db->port = getEnvData('ZT_DB_PORT');
|
||
\$config->db->name = getEnvData('ZT_DB_NAME');
|
||
\$config->db->user = getEnvData('ZT_DB_USER');
|
||
\$config->db->encoding = getEnvData('ZT_DB_ENCODING', 'UTF8');
|
||
\$config->db->password = getEnvData('ZT_DB_PASSWORD');
|
||
\$config->db->prefix = getEnvData('ZT_DB_PREFIX');
|
||
\$config->webRoot = getWebRoot();
|
||
\$config->default->lang = getEnvData('ZT_DEFAULT_LANG', 'zh-cn');
|
||
|
||
\$hasSlaveDB = (string)getEnvData('ENABLE_DB_SLAVE');
|
||
if(\$hasSlaveDB && \$hasSlaveDB != 'false')
|
||
{
|
||
\$slaveDB = new stdclass();
|
||
\$slaveDB->host = getEnvData('ZT_SLAVE_DB_HOST');
|
||
\$slaveDB->port = getEnvData('ZT_SLAVE_DB_PORT');
|
||
\$slaveDB->name = getEnvData('ZT_SLAVE_DB_NAME');
|
||
\$slaveDB->user = getEnvData('ZT_SLAVE_DB_USER');
|
||
\$slaveDB->password = getEnvData('ZT_SLAVE_DB_PASSWORD');
|
||
\$slaveDB->driver = getEnvData('ZT_DB_DRIVER');
|
||
\$slaveDB->encoding = getEnvData('ZT_DB_ENCODING');
|
||
\$slaveDB->prefix = getEnvData('ZT_DB_PREFIX');
|
||
\$config->slaveDBList = array(\$slaveDB);
|
||
}
|
||
EOT;
|
||
|
||
if($customSession) $configContent .= "\n\$config->customSession = true;";
|
||
|
||
if(is_writable($configRoot)) @file_put_contents($myConfigFile, $configContent);
|
||
$this->config->installed = true;
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 写入数据库配置信息。
|
||
* Set database params.
|
||
*
|
||
* @param object $data
|
||
* @access private
|
||
* @return bool
|
||
*/
|
||
private function setDBParam(object $data): bool
|
||
{
|
||
$this->config->db->driver = $data->dbDriver;
|
||
if($this->config->inQuickon)
|
||
{
|
||
$this->config->db->host = getenv('ZT_MYSQL_HOST');
|
||
$this->config->db->user = getenv('ZT_MYSQL_USER');
|
||
$this->config->db->encoding = 'UTF8';
|
||
$this->config->db->password = getenv('ZT_MYSQL_PASSWORD');
|
||
$this->config->db->port = getenv('ZT_MYSQL_PORT');
|
||
}
|
||
else
|
||
{
|
||
$this->config->db->host = $data->dbHost;
|
||
$this->config->db->user = $data->dbUser;
|
||
$this->config->db->encoding = $data->dbEncoding;
|
||
$this->config->db->password = $data->dbPassword;
|
||
$this->config->db->port = $data->dbPort;
|
||
}
|
||
$this->config->db->name = $data->dbName;
|
||
$this->config->db->prefix = $data->dbPrefix;
|
||
|
||
file_put_contents($this->install->buildDBLogFile('config'), json_encode(array('db' => $this->config->db, 'post' => $data)));
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* DevOps平台版设置session path。
|
||
* Set session save path.
|
||
*
|
||
* @access private
|
||
* @return bool
|
||
*/
|
||
private function setSessionPath(): bool
|
||
{
|
||
$customSession = false;
|
||
$checkSession = ini_get('session.save_handler') == 'files';
|
||
if($checkSession)
|
||
{
|
||
if(!session_save_path())
|
||
{
|
||
/* Restart the session because the session save path is null when start the session last time. */
|
||
session_write_close();
|
||
|
||
$tmpRootInfo = $this->getTmpRoot();
|
||
$sessionSavePath = $tmpRootInfo['path'] . 'session';
|
||
if(!is_dir($sessionSavePath)) mkdir($sessionSavePath, 0777, true);
|
||
|
||
session_save_path($sessionSavePath);
|
||
$customSession = true;
|
||
|
||
$sessionResult = $this->checkSessionSavePath();
|
||
if($sessionResult == 'fail') chmod($sessionSavePath, 0777);
|
||
|
||
session_start();
|
||
$this->session->set('installing', true);
|
||
}
|
||
}
|
||
|
||
$_SESSION['installing'] = true;
|
||
return $customSession;
|
||
}
|
||
|
||
/**
|
||
* 处理安装应用下拉选择的数据。
|
||
* Process application options.
|
||
*
|
||
* @param object $components
|
||
* @param object $cloudSolution
|
||
* @access protected
|
||
* @return object
|
||
*/
|
||
protected function processComponents(object $components, object $cloudSolution): object
|
||
{
|
||
foreach($components->category as $key => &$item)
|
||
{
|
||
if($item->name === 'pms')
|
||
{
|
||
unset($components->category[$key]);
|
||
continue;
|
||
}
|
||
|
||
if(in_array($item->name, array('analysis', 'artifact'))) array_unshift($item->choices, (object)array('name' => $this->lang->install->solution->skipInstall, 'version' => ''));
|
||
|
||
$item->schemaChoices = array();
|
||
foreach($item->choices as $cloudApp)
|
||
{
|
||
$appInfo = zget($cloudSolution->apps, $cloudApp->name, array());
|
||
$item->schemaChoices[$cloudApp->name] = zget($appInfo, 'alias', $cloudApp->name);
|
||
}
|
||
}
|
||
|
||
return $components;
|
||
}
|
||
}
|