<?php
namespace Module\Vendor\Web\Controller;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use ModStart\Admin\Auth\Admin;
use ModStart\Core\Dao\ModelUtil;
use ModStart\Core\Input\InputPackage;
use ModStart\Core\Input\Response;
use ModStart\Core\Util\RandomUtil;
use ModStart\Module\ModuleManager;
use PDO;
class InstallController extends Controller
{
public function lock()
{
$installLockFile = storage_path('install.lock');
if (file_exists($installLockFile)) {
return Response::send(0, 'install lock error -_-');
}
file_put_contents($installLockFile, 'lock');
return Response::send(0, 'install lock ok ^_^');
}
public function ping()
{
try {
$exitCode = Artisan::call("env");
$output = trim(Artisan::output());
if (0 == $exitCode) {
if (Str::contains($output, 'Current application environment')) {
return 'ok';
}
if (Str::contains($output, 'The application environment is')) {
return 'ok';
}
}
return 'ERROR: code=' . $exitCode . ', msg:' . $output;
} catch (\Exception $e) {
return 'ERROR:' . $e->getMessage();
}
}
public function prepare()
{
if (file_exists(storage_path('install.lock'))) {
return Response::jsonError("系统不能重复安装(请删除install.lock文件后重试)");
}
if (file_exists($p = base_path('.env'))) {
$content = file_get_contents($p);
if (str_contains($content, 'DB_HOST')) {
return Response::jsonError('请先清空.env文件');
}
}
$input = InputPackage::buildFromInput();
$dbHost = $input->getTrimString('db_host');
$dbPort = $input->getTrimString('db_port');
$dbDatabase = $input->getTrimString('db_database');
$dbUsername = $input->getTrimString('db_username');
$dbPassword = $input->getTrimString('db_password', '');
$dbPrefix = $input->getTrimString('db_prefix', '');
$username = $input->getTrimString('username');
$password = $input->getTrimString('password');
$installDemo = $input->getBoolean('installDemo');
$installLicense = $input->getBoolean('installLicense');
$installConfig = $input->getJson('INSTALL_CONFIG');
if (empty($dbHost)) {
return Response::jsonError("数据库主机名不能为空");
}
if (empty($dbPort)) {
return Response::jsonError("数据库端口不能为空");
}
if (empty($dbDatabase)) {
return Response::jsonError("数据库数据库不能为空");
}
if (empty($dbUsername)) {
return Response::jsonError("数据库用户名不能为空");
}
if (empty($username)) {
return Response::jsonError("管理用户不能为空");
}
if (empty($password)) {
return Response::jsonError("管理用户密码不能为空");
}
if (file_exists(base_path('license_url.txt')) && !$installLicense) {
return Response::jsonError("请先同意《软件安装许可协议》");
}
try {
new PDO("mysql:host=$dbHost;port=$dbPort;dbname=$dbDatabase", $dbUsername, $dbPassword);
} catch (\Exception $e) {
$msg = $e->getMessage();
if (str_contains($msg, 'Server sent charset unknown to the client')) {
return Response::generateError('数据库编码不支持:' . $msg);
} else if (str_contains($msg, 'Access denied for user')) {
return Response::generateError('用户密码不匹配:' . $msg);
}
Log::error('InstallError -> ' . $e->getMessage() . ' -> ' . $e->getTraceAsString());
return Response::jsonError('连接数据信息 ' . $dbHost . ':' . $dbPort . '.' . $dbDatabase . ' 失败!');
}
$envContent = file_get_contents(base_path('env.example'));
$envContent = preg_replace("/APP_DEBUG=(.*?)\\n/", "APP_DEBUG=false\n", $envContent);
$envContent = preg_replace("/DB_HOST=(.*?)\\n/", "DB_HOST=" . $dbHost . "\n", $envContent);
$envContent = preg_replace("/DB_PORT=(.*?)\\n/", "DB_PORT=" . $dbPort . "\n", $envContent);
$envContent = preg_replace("/DB_DATABASE=(.*?)\\n/", "DB_DATABASE=" . $dbDatabase . "\n", $envContent);
$envContent = preg_replace("/DB_USERNAME=(.*?)\\n/", "DB_USERNAME=" . $dbUsername . "\n", $envContent);
$envContent = preg_replace("/DB_PASSWORD=(.*?)\\n/", "DB_PASSWORD=" . $dbPassword . "\n", $envContent);
$envContent = preg_replace("/DB_PREFIX=(.*?)\\n/", "DB_PREFIX=" . $dbPrefix . "\n", $envContent);
$envContent = preg_replace("/APP_KEY=(.*?)\\n/", "APP_KEY=" . RandomUtil::string(32) . "\n", $envContent);
$envContent = preg_replace("/ENCRYPT_KEY=(.*?)\\n/", "ENCRYPT_KEY=" . RandomUtil::string(32) . "\n", $envContent);
if (!empty($installConfig['envs'])) {
foreach ($installConfig['envs'] as $envField) {
$envContent = preg_replace(
"/" . $envField['name'] . "=(.*?)\\n/",
$envField['name'] . "=" . $input->getTrimString($envField['name']) . "\n",
$envContent
);
}
}
file_put_contents(base_path('.env'), $envContent);
return Response::jsonSuccess();
}
public function execute()
{
if (file_exists(storage_path('install.lock'))) {
return Response::jsonError("系统不能重复安装(请删除install.lock文件后重试)");
}
$input = InputPackage::buildFromInput();
$username = $input->getTrimString("username");
$password = $input->getTrimString("password");
$installDemo = $input->getBoolean('installDemo');
if (empty($username)) {
return Response::jsonError("管理用户名为空");
}
if (empty($password)) {
return Response::jsonError("管理用户密码为空");
}
set_time_limit(0);
$exitCode = 0;
try {
$exitCode = Artisan::call("migrate");
} catch (\Exception $e) {
return $this->handleException($e);
}
if (0 != $exitCode) {
return Response::jsonError("安装错误 exitCode($exitCode)");
}
$adminUserCount = ModelUtil::count('admin_user');
if ($adminUserCount === 0) {
Admin::add($username, $password);
}
* 预安装所有模块
*/
foreach (ModuleManager::listAllInstalledModulesInRequiredOrder() as $module) {
if (!ModuleManager::isExists($module)) {
continue;
}
try {
$ret = ModuleManager::install($module);
} catch (\Exception $e) {
return $this->handleException($e);
}
if (Response::isError($ret)) {
return Response::generateError($ret['msg']);
}
}
if ($installDemo && file_exists($file = public_path('data_demo/data.php'))) {
$data = include($file);
if (!empty($data['inserts'])) {
foreach ($data['inserts'] as $table => $records) {
ModelUtil::insertAll($table, $records);
}
}
if (!empty($data['updates'])) {
foreach ($data['updates'] as $record) {
DB::table($record['table'])->where($record['where'])->update($record['update']);
}
}
}
file_put_contents(storage_path('install.lock'), 'lock');
return Response::json(0, '安装成功,点击即将跳转到管理后台', null, '/admin');
}
private function handleException(\Exception $e)
{
$msg = $e->getMessage();
$traces = $e->getTraceAsString();
if (preg_match("/Table '(.*?)' already exists/", $msg, $mat)) {
return Response::jsonError('数据表 ' . $mat[1] . ' 已经存在(可能您使用了一个非空的数据库,请删除表或更新数据库)');
}
if (preg_match("/Duplicate column name '(.*?)'/", $msg, $mat)) {
$field = $mat[1];
$file = null;
if (preg_match("/(module\\/.*?\\/Migrate\\/.*?\\.php)/", $traces, $mat)) {
$file = $mat[1];
}
return Response::jsonError('数据表字段 ' . $field . ' 已经存在(请查看' . $file . '迁移文件配置)');
}
throw $e;
}
}