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 ($this->defaultModule as $m) { $module = new InstallLocalModule($m); $module->installModuleTables(); $module->installModuleSeeds(); $this->output->info('🎉 module [' . $m . '] installed successfully'); } } /** * 回滚数据 * * @time 2020年09月07日 * @return void */ protected function migrateRollback() { foreach ($this->defaultModule as $m) { $module = new InstallLocalModule($m); $module->rollbackModuleTable(); $this->output->info('🎉' . $m . ' tables rollback successfully'); } } /** * 安装第四步 * * @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 failed,you 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 初始账号: catch@admin.com 初始密码: catchadmin ', $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'; } }