cms-manage/app/controller/backend/SystemInstallController.php

538 lines
18 KiB
PHP
Raw Normal View History

2025-02-13 08:21:56 +00:00
<?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;
}
}