538 lines
18 KiB
PHP
538 lines
18 KiB
PHP
<?php
|
||
declare (strict_types=1);
|
||
|
||
namespace app\controller\backend;
|
||
|
||
use app\BaseController;
|
||
use app\exception\InstallException;
|
||
use app\model\Admin;
|
||
use app\model\Model;
|
||
use app\model\Route;
|
||
use app\model\Website;
|
||
use app\model\WebsiteLang;
|
||
use app\model\WebsiteServer;
|
||
use app\model\WebsiteSetting;
|
||
use app\service\ThemeService;
|
||
use app\validate\SystemInstallValidate;
|
||
use think\exception\ValidateException;
|
||
use think\facade\Db;
|
||
use think\facade\Log;
|
||
use think\facade\View;
|
||
use think\Validate;
|
||
|
||
class SystemInstallController extends BaseController
|
||
{
|
||
/**
|
||
* 显示资源列表
|
||
*
|
||
*/
|
||
public function index()
|
||
{
|
||
if (hcInstalled()) {
|
||
return redirect('/admin.php');
|
||
}
|
||
|
||
// 向huocms官网请求是否认证
|
||
$domain = request()->host();
|
||
|
||
if (!empty($domain)) {
|
||
$authRes = curlPost(config('system.auth_query_url'), ['domain' => $domain])['data'];
|
||
Log::info('auth_query_url:' . $authRes);
|
||
}
|
||
|
||
$year = date('Y', time());
|
||
$month = date('m', time());
|
||
$day = date('d', time());
|
||
View::assign(['year' => $year, 'month' => $month, 'day' => $day]);
|
||
return View::fetch(CMS_ROOT . 'data/install/install.html');
|
||
}
|
||
|
||
public function monitor(): string
|
||
{
|
||
// if (file_exists_case('data/conf/config.php')) {
|
||
// @unlink('data/conf/config.php');
|
||
// }
|
||
$data = [];
|
||
$data['phpversion'] = @phpversion();
|
||
$data['os'] = PHP_OS;
|
||
$tmp = function_exists('gd_info') ? gd_info() : [];
|
||
// $server = $_SERVER["SERVER_SOFTWARE"];
|
||
// $host = $this->request->host();
|
||
// $name = $_SERVER["SERVER_NAME"];
|
||
// $max_execution_time = ini_get('max_execution_time');
|
||
// $allow_reference = (ini_get('allow_call_time_pass_reference') ? '<font color=green>[√]On</font>' : '<font color=red>[×]Off</font>');
|
||
// $allow_url_fopen = (ini_get('allow_url_fopen') ? '<font color=green>[√]On</font>' : '<font color=red>[×]Off</font>');
|
||
// $safe_mode = (ini_get('safe_mode') ? '<font color=red>[×]On</font>' : '<font color=green>[√]Off</font>');
|
||
$err = 0;
|
||
if (empty($tmp['GD Version'])) {
|
||
$gd = '/system_file/install/image/success_icon.jpg';
|
||
$err++;
|
||
} else {
|
||
$gd = '/system_file/install/image/error_icon.png ' . $tmp['GD Version'];
|
||
}
|
||
|
||
if (class_exists('pdo')) {
|
||
$data['pdo'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['pdo'] = '/system_file/install/image/error_icon.png';
|
||
$err++;
|
||
}
|
||
|
||
if (extension_loaded('pdo_mysql')) {
|
||
$data['pdo_mysql'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['pdo_mysql'] = '/system_file/install/image/error_icon.png';
|
||
$err++;
|
||
}
|
||
|
||
if (extension_loaded('curl')) {
|
||
$data['curl'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['curl'] = '/system_file/install/image/error_icon.png';
|
||
$err++;
|
||
}
|
||
|
||
if (extension_loaded('gd')) {
|
||
$data['gd'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['gd'] = '/system_file/install/image/error_icon.png';
|
||
if (function_exists('imagettftext')) {
|
||
$data['gd'] .= '/system_file/install/image/error_icon.png';
|
||
}
|
||
$err++;
|
||
}
|
||
|
||
if (extension_loaded('mbstring')) {
|
||
$data['mbstring'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['mbstring'] = '/system_file/install/image/error_icon.png';
|
||
if (function_exists('imagettftext')) {
|
||
$data['mbstring'] .= '/system_file/install/image/error_icon.png';
|
||
}
|
||
$err++;
|
||
}
|
||
|
||
if (extension_loaded('fileinfo')) {
|
||
$data['fileinfo'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['fileinfo'] = '/system_file/install/image/error_icon.png';
|
||
$err++;
|
||
}
|
||
|
||
if (ini_get('file_uploads')) {
|
||
$data['upload_size'] = ini_get('upload_max_filesize');
|
||
} else {
|
||
$data['upload_size'] = '未开启';
|
||
$err++;
|
||
}
|
||
|
||
if (function_exists('session_start')) {
|
||
$data['session'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$data['session'] = '/system_file/install/image/error_icon.png';
|
||
$err++;
|
||
}
|
||
|
||
if (version_compare(phpversion(), '7.2.0', '>=') && version_compare(phpversion(), '7.0.0', '<') && ini_get('always_populate_raw_post_data') != -1) {
|
||
$data['always_populate_raw_post_data'] = '未关闭';
|
||
$data['show_always_populate_raw_post_data_tip'] = true;
|
||
$err++;
|
||
} else {
|
||
$data['always_populate_raw_post_data'] = '已关闭';
|
||
}
|
||
|
||
$folders = [
|
||
realpath(CMS_ROOT . 'data') . DIRECTORY_SEPARATOR,
|
||
realpath(CMS_ROOT . 'runtime') . DIRECTORY_SEPARATOR,
|
||
realpath(CMS_ROOT . 'public/themes') . DIRECTORY_SEPARATOR,
|
||
realpath(CMS_ROOT . 'public/storage') . DIRECTORY_SEPARATOR,
|
||
realpath(CMS_ROOT . 'public/poster_preview') . DIRECTORY_SEPARATOR,
|
||
];
|
||
$newFolders = [];
|
||
foreach ($folders as $dir) {
|
||
$testDir = $dir;
|
||
sp_dir_create($testDir);
|
||
if (sp_testwrite($testDir)) {
|
||
$newFolders[$dir]['w'] = true;
|
||
} else {
|
||
$newFolders[$dir]['w'] = false;
|
||
$err++;
|
||
}
|
||
if (is_readable($testDir)) {
|
||
$newFolders[$dir]['r'] = true;
|
||
} else {
|
||
$newFolders[$dir]['r'] = false;
|
||
$err++;
|
||
}
|
||
if ($newFolders[$dir]['w'] && $newFolders[$dir]['r']) {
|
||
$newFolders[$dir]['icon'] = '/system_file/install/image/success_icon.jpg';
|
||
} else {
|
||
$newFolders[$dir]['icon'] = '/system_file/install/image/error_icon.png';
|
||
|
||
}
|
||
}
|
||
$data['err'] = $err;
|
||
$data['folders'] = $newFolders;
|
||
View::assign($data);
|
||
return View::fetch(CMS_ROOT . 'data/install/monitor.html');
|
||
}
|
||
|
||
public function configure(): string
|
||
{
|
||
return View::fetch(CMS_ROOT . 'data/install/configure.html');
|
||
}
|
||
|
||
public function create(): string
|
||
{
|
||
$param = request()->param();
|
||
if (empty($param['username'])) {
|
||
$param['username'] = 'admin@admin.com';
|
||
}
|
||
if (empty($param['password'])) {
|
||
$param['password'] = 'huocms.com';
|
||
}
|
||
$dbConfig = [
|
||
'type' => 'mysql',
|
||
// 连接名
|
||
'hostname' => $param['hostname'],
|
||
// 用户名
|
||
'username' => $param['username'],
|
||
// 密码
|
||
'password' => $param['password'],
|
||
// 端口
|
||
'hostport' => $param['hostport'],
|
||
// 数据库编码默认采用utf8mb4
|
||
'charset' => $param['charset'],
|
||
// 数据库表前缀
|
||
'prefix' => $param['prefix'],
|
||
];
|
||
$this->updateDbConfig($dbConfig);
|
||
$sql = "CREATE DATABASE IF NOT EXISTS `{$param['database']}` DEFAULT CHARACTER SET " . $param['charset'];
|
||
$db = Db::connect('install_db');
|
||
$db->execute($sql);
|
||
$dbConfig['database'] = $param['database'];
|
||
$this->exchangeEnv($dbConfig);
|
||
session('install.db_config', $dbConfig);
|
||
$sql = hcSplitSql(CMS_ROOT . '/data/install/install.sql', $dbConfig['prefix'], $dbConfig['charset']);
|
||
session('install.sql', $sql);
|
||
View::assign('sql_count', count($sql));
|
||
session('install.error', 0);
|
||
session('install.admin_info', [
|
||
'name' => $param['admin'],
|
||
'account' => $param['email'],
|
||
'password' => makePassword($param['admin_pass'])
|
||
]);
|
||
return View::fetch(CMS_ROOT . 'data/install/create.html');
|
||
}
|
||
|
||
public function install()
|
||
{
|
||
$dbConfig = session('install.db_config');
|
||
$sql = session('install.sql');
|
||
|
||
if (empty($dbConfig) || empty($sql)) {
|
||
return json([
|
||
'code' => -1,
|
||
'data' => '',
|
||
'msg' => '非法安装!'
|
||
]);
|
||
}
|
||
|
||
$sqlIndex = $this->request->param('sql_index', 0, 'intval');
|
||
|
||
$this->updateDbConfig($dbConfig);
|
||
$db = Db::connect('install_db');
|
||
|
||
if ($sqlIndex >= count($sql)) {
|
||
return json([
|
||
'code' => 200,
|
||
'data' => '',
|
||
'msg' => '安装完成!'
|
||
]);
|
||
}
|
||
|
||
$sqlToExec = $sql[$sqlIndex] . ';';
|
||
|
||
$result = sp_execute_sql($db, $sqlToExec);
|
||
|
||
if (!empty($result['error'])) {
|
||
return json([
|
||
'code' => -1,
|
||
'data' => [
|
||
'sql' => $sqlToExec,
|
||
'exception' => $result['exception']
|
||
],
|
||
'msg' => '安装失败!'
|
||
]);
|
||
} else {
|
||
return json([
|
||
'code' => 0,
|
||
'data' => $result,
|
||
'msg' => '安装成功!'
|
||
]);
|
||
}
|
||
}
|
||
|
||
public function exchangeEnv($dbConfig)
|
||
{
|
||
$envFile = CMS_ROOT . '.env';
|
||
$example = CMS_ROOT . '.example.env';
|
||
|
||
if (file_exists($example)) {
|
||
copy($example, $envFile);
|
||
} else {
|
||
touch($envFile);
|
||
$initArray = [
|
||
"APP_DEBUG = true",
|
||
"APP_HOST = http://localhost",
|
||
"",
|
||
"[APP]",
|
||
"DEFAULT_TIMEZONE = Asia/Shanghai",
|
||
"",
|
||
"[DATABASE]",
|
||
"TYPE = mysql",
|
||
"HOSTNAME = 127.0.0.1",
|
||
"DATABASE = huo_cms",
|
||
"USERNAME = root",
|
||
"PASSWORD = ",
|
||
"HOSTPORT = 3306",
|
||
"CHARSET = utf8mb4",
|
||
"DEBUG = true",
|
||
"PREFIX = hc_",
|
||
"",
|
||
"[LANG]",
|
||
"default_lang = zh",
|
||
];
|
||
file_put_contents($envFile, implode(PHP_EOL, $initArray));
|
||
}
|
||
|
||
$merge = [
|
||
'app_debug' => true,
|
||
'app_host' => request()->domain(),
|
||
];
|
||
$data = [];
|
||
foreach (array_merge($merge, $dbConfig) as $key => $val) {
|
||
$key = strtoupper($key);
|
||
$data[$key] = $val;
|
||
}
|
||
|
||
$this->updateEnv($envFile, $data);
|
||
}
|
||
|
||
public function updateEnv($envFile, $data = array())
|
||
{
|
||
$oldEnv = file($envFile);
|
||
if (!count($data)) {
|
||
return;
|
||
}
|
||
if (array_keys($data) === range(0, count($data) - 1)) {
|
||
return;
|
||
}
|
||
$pattern = '/([^\=]*)\=[^\n]*/';
|
||
$newEnv = [];
|
||
foreach ($oldEnv as $line) {
|
||
preg_match($pattern, $line, $matches);
|
||
|
||
if (!count($matches)) {
|
||
$newEnv[] = $line;
|
||
continue;
|
||
}
|
||
|
||
if (!key_exists(trim($matches[1]), $data)) {
|
||
$newEnv[] = $line;
|
||
continue;
|
||
}
|
||
|
||
$line = trim($matches[1]) . "={$data[trim($matches[1])]}\n";
|
||
$newEnv[] = $line;
|
||
}
|
||
$newContent = implode('', $newEnv);
|
||
|
||
file_put_contents($envFile, $newContent);
|
||
}
|
||
|
||
public function userCheck(): \think\response\Json
|
||
{
|
||
$param = request()->param();
|
||
try {
|
||
validate(SystemInstallValidate::class)->check($param);
|
||
} catch (ValidateException $e) {
|
||
return jsonReturn(-1, $e->getError());
|
||
}
|
||
return jsonReturn(0, 'success');
|
||
}
|
||
|
||
public function testPass(): \think\response\Json
|
||
{
|
||
$param = request()->param();
|
||
$dbConfig = [
|
||
'type' => 'mysql',
|
||
// 连接名
|
||
'hostname' => $param['hostname'],
|
||
// 数据库名
|
||
'username' => $param['username'],
|
||
// 密码
|
||
'password' => $param['password'],
|
||
// 端口
|
||
'hostport' => $param['hostport'],
|
||
];
|
||
$this->updateDbConfig($dbConfig);
|
||
$supportInnoDb = false;
|
||
try {
|
||
$db = Db::connect('install_db');
|
||
$engines = $db->query("SHOW ENGINES;");
|
||
foreach ($engines as $engine) {
|
||
if ($engine['Engine'] == 'InnoDB' && $engine['Support'] != 'NO') {
|
||
$supportInnoDb = true;
|
||
break;
|
||
}
|
||
}
|
||
} catch (\Exception $e) {
|
||
return jsonReturn(-1, '数据库账号或密码不正确!' . $e->getMessage());
|
||
}
|
||
if (!$supportInnoDb) {
|
||
return jsonReturn(-2, '数据库账号密码验证通过,但不支持InnoDb!');
|
||
} else {
|
||
return jsonReturn(0, 'success');
|
||
}
|
||
}
|
||
|
||
public function installCompleteCheck(): \think\response\Json
|
||
{
|
||
|
||
$admin = session("install.admin_info");
|
||
if (empty($admin)) {
|
||
return jsonReturn(-1, '用户创建失败,请重试');
|
||
}
|
||
Db::startTrans();
|
||
try {
|
||
// 创建管理员
|
||
$Admin = new Admin();
|
||
$admin['seller_id'] = 1;
|
||
$admin['status'] = 1;
|
||
$admin['group'] = 1;
|
||
$res = $Admin->addAdmin($admin)['data'];
|
||
$res->role()->attach(1, ['seller_id' => 1]);
|
||
session('adminId', $res['id']);
|
||
$website = new Website();
|
||
$siteParam = [
|
||
'title' => '演示站点',
|
||
'domain' => request()->host()
|
||
];
|
||
// 创建站点
|
||
// 1. 保存站点到数据库
|
||
$res = $website->addWebsite($siteParam);
|
||
if ($res['data'] != 1) {
|
||
throw new InstallException();
|
||
}
|
||
// 2. 生成一份默认的站点配置,配置的值为空
|
||
$tmpData = config('system.website_setting');
|
||
$sysData = [
|
||
"setting" => json_encode($tmpData),
|
||
"website_id" => $res['data'],
|
||
"lang" => "zh"
|
||
];
|
||
$siteSetting = new WebsiteSetting();
|
||
$siteSetting->addWebsiteSetting($sysData);
|
||
// 3. 选择站点语言简体中文,服务器为本地服务器
|
||
$langData[] = [
|
||
'seller_id' => 1,
|
||
'website_id' => $res['data'],
|
||
'lang_name' => '简体中文',
|
||
'lang' => 'zh',
|
||
];
|
||
$WebsiteLang = new WebsiteLang();
|
||
$WebsiteLang->addWebsiteLang($langData);
|
||
$serverData = [
|
||
'seller_id' => 1,
|
||
'website_id' => $res['data'],
|
||
'type' => 1,
|
||
];
|
||
$WebsiteServer = new WebsiteServer();
|
||
$WebsiteServer->addWebsiteServer($serverData);
|
||
// 4.生成路由
|
||
$Route = new Route();
|
||
$Route->updateRoute(['seller_id' => 1], ['website_id' => $res['data']]);
|
||
$Route->getRoutes($res['data'], 1, 'zh');
|
||
// 5.安装模版
|
||
$ThemeService = new ThemeService();
|
||
$ThemeService->installTheme('demo', $res['data'], 1);
|
||
|
||
createInstallFile();
|
||
session("install.step", 4);
|
||
Db::commit();
|
||
} catch (InstallException $e) {
|
||
@unlink(CMS_ROOT . 'public/system_file/install.lock');
|
||
Db::rollback();
|
||
return jsonReturn(-3, '安装失败,请清空数据库后重试');
|
||
} catch (\Exception $e) {
|
||
@unlink(CMS_ROOT . 'public/system_file/install.lock');
|
||
Db::rollback();
|
||
return jsonReturn(-1, '用户创建失败,请重试' . $e->getMessage());
|
||
}
|
||
return jsonReturn(0, 'success');
|
||
}
|
||
|
||
public function completeCheck(): \think\response\Json
|
||
{
|
||
if (session("install.step") == 4) {
|
||
return jsonReturn(0, '安装成功');
|
||
} else {
|
||
return jsonReturn(-1, '安装失败');
|
||
}
|
||
}
|
||
|
||
public function complete(): string
|
||
{
|
||
return View::fetch(CMS_ROOT . 'data/install/complete.html');
|
||
}
|
||
|
||
private function updateDbConfig($dbConfig)
|
||
{
|
||
$oldDbConfig = config('database');
|
||
$oldDbConfig['connections']['install_db'] = $dbConfig;
|
||
config($oldDbConfig, 'database');
|
||
}
|
||
|
||
public function write_ini_file($assoc_arr, $path, $has_sections = FALSE): bool
|
||
{
|
||
$content = "";
|
||
if ($has_sections) {
|
||
foreach ($assoc_arr as $key => $elem) {
|
||
$content .= "[" . $key . "]n";
|
||
foreach ($elem as $key2 => $elem2) {
|
||
if (is_array($elem2)) {
|
||
for ($i = 0; $i < count($elem2); $i++) {
|
||
$content .= $key2 . "[] = " . $elem2[$i] . "\r\n";
|
||
}
|
||
} else if ($elem2 == "") {
|
||
$content .= $key2 . " = n";
|
||
} else {
|
||
$content .= $key2 . " = " . $elem2 . "\r\n";
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
foreach ($assoc_arr as $key => $elem) {
|
||
if (is_array($elem)) {
|
||
for ($i = 0; $i < count($elem); $i++) {
|
||
$content .= $key . "[] = " . $elem[$i] . "\r\n";
|
||
}
|
||
} else if ($elem == "") {
|
||
$content .= $key . " = n";
|
||
} else {
|
||
$content .= $key . " = " . $elem . "\r\n";
|
||
}
|
||
}
|
||
}
|
||
if (!$handle = fopen($path, 'w')) {
|
||
return false;
|
||
}
|
||
if (!fwrite($handle, $content)) {
|
||
return false;
|
||
}
|
||
fclose($handle);
|
||
return true;
|
||
}
|
||
}
|