catchAdmin/extend/catcher/command/install/InstallProjectCommand.php

381 lines
12 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
namespace catcher\command\install;
use catcher\CatchAdmin;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\Console;
class InstallProjectCommand extends Command
{
protected $databaseLink = [];
protected $defaultModule = ['permissions', 'system'];
protected function configure()
{
$this->setName('catch:install')
->addOption('reinstall', '-r',Option::VALUE_NONE, 'reinstall back')
->setDescription('install project');
}
/**
*
* @time 2019年11月29日
* @param Input $input
* @param Output $output
* @return int|void|null
*/
protected function execute(Input $input, Output $output)
{
if ($input->getOption('reinstall')) {
$this->reInstall();
$this->project();
} else {
$this->detectionEnvironment();
$this->firstStep();
$this->secondStep();
$this->thirdStep();
$this->finished();
$this->project();
}
}
/**
* 环境检测
*
* @time 2019年11月29日
* @return void
*/
protected function detectionEnvironment(): void
{
$this->output->info('environment begin to check...');
if (version_compare(PHP_VERSION, '7.1.0', '<')) {
$this->output->error('php version should >= 7.1.0');
exit();
}
$this->output->info('php version ' . PHP_VERSION);
if (!extension_loaded('mbstring')) {
$this->output->error('mbstring extension not install');exit();
}
$this->output->info('mbstring extension is installed');
if (!extension_loaded('json')) {
$this->output->error('json extension not install');
exit();
}
$this->output->info('json extension is installed');
if (!extension_loaded('openssl')) {
$this->output->error('openssl extension not install');
exit();
}
$this->output->info('openssl extension is installed');
if (!extension_loaded('pdo')) {
$this->output->error('pdo extension not install');
exit();
}
$this->output->info('pdo extension is installed');
if (!extension_loaded('xml')) {
$this->output->error('xml extension not install');
exit();
}
$this->output->info('xml extension is installed');
$this->output->info('🎉 environment checking finished');
}
/**
* 安装第一步
*
* @time 2019年11月29日
* @return mixed
*/
protected function firstStep()
{
if (file_exists($this->app->getRootPath() . '.env')) {
return false;
}
// 设置 app domain
$appDomain = strtolower($this->output->ask($this->input, '👉 first, you should set app domain: '));
if (strpos('http://', $appDomain) === false || strpos('https://', $appDomain) === false) {
$appDomain = 'http://' . $appDomain;
}
$answer = strtolower($this->output->ask($this->input, '🤔️ Did You Need to Set Database information? (Y/N): '));
if ($answer === 'y' || $answer === 'yes') {
$charset = $this->output->ask($this->input, '👉 please input database charset, default (utf8mb4):') ? : 'utf8mb4';
$database = '';
while (!$database) {
$database = $this->output->ask($this->input, '👉 please input database name: ');
if ($database) {
break;
}
}
$host = $this->output->ask($this->input, '👉 please input database host, default (127.0.0.1):') ? : '127.0.0.1';
$port = $this->output->ask($this->input, '👉 please input database host port, default (3306):') ? : '3306';
$prefix = $this->output->ask($this->input, '👉 please input table prefix, default (null):') ? : '';
$username = $this->output->ask($this->input, '👉 please input database username default (root): ') ? : 'root';
$password = '';
$tryTimes = 0;
while (!$password) {
$password = $this->output->ask($this->input, '👉 please input database password: ');
if ($password) {
break;
}
// 尝试三次以上未填写,视为密码空
$tryTimes++;
if (!$password && $tryTimes > 2) {
break;
}
}
$this->databaseLink = [$host, $database, $username, $password, $port, $charset, $prefix];
$this->generateEnvFile($host, $database, $username, $password, $port, $charset, $prefix, $appDomain);
}
}
/**
* 安装第二部
*
* @time 2019年11月29日
* @return void
*/
protected function secondStep(): void
{
if (file_exists($this->getEnvFilePath())) {
$connections = \config('database.connections');
// 因为 env file 导致安装失败
if (!$this->databaseLink) {
unlink($this->getEnvFilePath());
$this->execute($this->input, $this->output);
} else {
[
$connections['mysql']['hostname'],
$connections['mysql']['database'],
$connections['mysql']['username'],
$connections['mysql']['password'],
$connections['mysql']['hostport'],
$connections['mysql']['charset'],
$connections['mysql']['prefix'],
] = $this->databaseLink ?: [
env('mysql.hostname')
];
\config([
'connections' => $connections,
], 'database');
$this->migrateAndSeeds();
}
}
}
/**
* 生成表结构
*
* @time 2020年01月20日
* @return void
*/
protected function migrateAndSeeds(): void
{
foreach (CatchAdmin::getModulesDirectory() as $directory) {
$moduleInfo = CatchAdmin::getModuleInfo($directory);
if (!empty($moduleInfo) && is_dir(CatchAdmin::moduleMigrationsDirectory($moduleInfo['alias']))) {
if (in_array($moduleInfo['alias'], $this->defaultModule)) {
$output = Console::call('catch-migrate:run', [$moduleInfo['alias']]);
$this->output->info(sprintf('module [%s] migrations %s', $moduleInfo['alias'], $output->fetch()));
$seedOut = Console::call('catch-seed:run', [$moduleInfo['alias']]);
$this->output->info(sprintf('module [%s] seeds %s', $moduleInfo['alias'], $seedOut->fetch()));
}
}
}
}
/**
* 回滚数据
*
* @time 2020年09月07日
* @return void
*/
protected function migrateRollback()
{
foreach (CatchAdmin::getModulesDirectory() as $directory) {
$moduleInfo = CatchAdmin::getModuleInfo($directory);
if (!empty($moduleInfo) && is_dir(CatchAdmin::moduleMigrationsDirectory($moduleInfo['alias']))) {
if (in_array($moduleInfo['alias'], $this->defaultModule)) {
$rollbackOut = Console::call('catch-migrate:rollback', [$moduleInfo['alias'], '-f']);
// $this->output->info(sprintf('module [%s] [%s] rollback %s', $moduleInfo['alias'], basename($migration), $rollbackOut->fetch()));
}
}
}
}
/**
* 安装第四步
*
* @time 2019年11月29日
* @return void
*/
protected function thirdStep(): void
{
// Console::call('catch:cache');
}
/**
* finally
*
* @time 2019年11月30日
* @return void
*/
protected function finished(): void
{
// todo something
// create jwt
Console::call('jwt:create');
// create service
Console::call('catch-service:discover');
}
/**
* generate env file
*
* @time 2019年11月29日
* @param $host
* @param $database
* @param $username
* @param $password
* @param $port
* @param $charset
* @param $prefix
* @param $appDomain
* @return void
*/
protected function generateEnvFile($host, $database, $username, $password, $port, $charset, $prefix, $appDomain): void
{
try {
$env = \parse_ini_file(root_path() . '.example.env', true);
$env['APP']['DOMAIN'] = $appDomain;
$env['DATABASE']['HOSTNAME'] = $host;
$env['DATABASE']['DATABASE'] = $database;
$env['DATABASE']['USERNAME'] = $username;
$env['DATABASE']['PASSWORD'] = $password;
$env['DATABASE']['HOSTPORT'] = $port;
$env['DATABASE']['CHARSET'] = $charset;
if ($prefix) {
$env['DATABASE']['PREFIX'] = $prefix;
}
$dotEnv = '';
foreach ($env as $key => $e) {
if (is_string($e)) {
$dotEnv .= sprintf('%s = %s', $key, $e === '1' ? 'true' : ($e === '' ? 'false' : $e)) . PHP_EOL;
$dotEnv .= PHP_EOL;
} else {
$dotEnv .= sprintf('[%s]', $key) . PHP_EOL;
foreach ($e as $k => $v) {
$dotEnv .= sprintf('%s = %s', $k, $v === '1' ? 'true' : ($v === '' ? 'false' : $v)) . PHP_EOL;
}
$dotEnv .= PHP_EOL;
}
}
if ($this->getEnvFile()) {
$this->output->info('env file has been generated');
}
if ((new \mysqli($host, $username, $password, null, $port))->query(sprintf('CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARSET %s COLLATE %s_general_ci;',
$database, $charset, $charset))) {
$this->output->info(sprintf('🎉 create database %s successfully', $database));
} else {
$this->output->warning(sprintf('create database %s failedyou need create database first by yourself', $database));
}
} catch (\Exception $e) {
$this->output->error($e->getMessage());
exit(0);
}
file_put_contents(root_path() . '.env', $dotEnv);
}
/**
*
* @time 2019年11月29日
* @return string
*/
protected function getEnvFile(): string
{
return file_exists(root_path() . '.env') ? root_path() . '.env' : '';
}
protected function project()
{
$year = date('Y');
$this->output->info('🎉 project is installed, welcome!');
$this->output->info(sprintf('
/-------------------- welcome to use -------------------------\
| __ __ ___ __ _ |
| _________ _/ /______/ /_ / | ____/ /___ ___ (_)___ |
| / ___/ __ `/ __/ ___/ __ \ / /| |/ __ / __ `__ \/ / __ \ |
| / /__/ /_/ / /_/ /__/ / / / / ___ / /_/ / / / / / / / / / / |
| \___/\__,_/\__/\___/_/ /_/ /_/ |_\__,_/_/ /_/ /_/_/_/ /_/ |
| |
\ __ __ __ __ _ __ _ __ enjoy it ! _ __ __ __ __ __ __ ___ _ @ 2017 %s
版本: %s
初始账号: admin@gmail.com
初始密码: admin
', $year, CatchAdmin::VERSION));
exit(0);
}
protected function reInstall(): void
{
$ask = strtolower($this->output->ask($this->input,'reset project? (Y/N)'));
if ($ask === 'y' || $ask === 'yes' ) {
$this->migrateRollback();
$this->migrateAndSeeds();
$this->finished();
}
}
/**
* 获取 env path
*
* @time 2020年04月06日
* @return string
*/
protected function getEnvFilePath()
{
return root_path() . '.env';
}
}