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

538 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}