portal.mkgtu.ru/console/controllers/InstallLkController.php

772 lines
22 KiB
PHP
Raw Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace console\controllers;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\console\widgets\Table;
use yii\helpers\ArrayHelper;
use yii\helpers\Console;
use yii\helpers\FileHelper;
class InstallLkController extends Controller
{
public $check_environments;
public $php_path;
public $db_type;
public $db_host;
public $db_port;
public $db_username;
public $db_password;
public $db_name;
public $db_silent_setup;
public $domain;
public $portal_name;
public $enable_1c_services;
public $odinc_url;
public $odinc_url_stud;
public $odinc_url_abit;
public $odinc_login_stud;
public $odinc_login_abit;
public $odinc_password_stud;
public $odinc_password_abit;
public $server_type;
public $help = false;
private $rootPath = '';
private $stepNumber = 1;
const YES_LIST = [
'y',
'д',
'да',
'yes',
];
const NO_LIST = [
'н',
'n',
'no',
'нет',
];
const SERVER_OTHER = 0;
const SERVER_APACHE = 1;
const SERVER_IIS = 2;
const SERVERS_LIST = [
self::SERVER_IIS => 'IIS',
self::SERVER_APACHE => 'Apache',
self::SERVER_OTHER => 'Другой (nginx и др.)',
];
public function options($actionID)
{
return [
'help',
'domain',
'db_type',
'db_host',
'db_port',
'db_name',
'php_path',
'odinc_url',
'db_username',
'db_password',
'server_type',
'portal_name',
'odinc_url_stud',
'odinc_url_abit',
'db_silent_setup',
'odinc_login_stud',
'odinc_login_abit',
'check_environments',
'enable_1c_services',
'odinc_password_stud',
'odinc_password_abit',
];
}
public function optionAliases()
{
return [
'h' => 'help',
'd' => 'domain',
'dt' => 'db_type',
'dh' => 'db_host',
'dp' => 'db_port',
'dn' => 'db_name',
'pp' => 'php_path',
'ou' => 'odinc_url',
'du' => 'db_username',
'st' => 'server_type',
'pn' => 'portal_name',
'dpw' => 'db_password',
'ds' => 'db_silent_setup',
'ous' => 'odinc_url_stud',
'oua' => 'odinc_url_abit',
'ols' => 'odinc_login_stud',
'ola' => 'odinc_login_abit',
'ce' => 'check_environments',
'es' => 'enable_1c_services',
'ops' => 'odinc_password_stud',
'opa' => 'odinc_password_abit',
];
}
public function beforeAction($action)
{
if (!parent::beforeAction($action)) {
return false;
}
$this->check_environments = $this->convertToBoolean($this->check_environments, true);
if (!isset($this->check_environments)) {
return false;
}
$this->db_silent_setup = $this->convertToBoolean($this->db_silent_setup, false);
if (!isset($this->db_silent_setup)) {
return false;
}
if (empty($this->php_path)) {
$this->php_path = 'php';
}
if (empty($this->db_name)) {
$this->db_name = 'lk_db';
}
if (empty($this->domain)) {
$this->domain = 'localhost';
}
if (empty($this->db_password)) {
$this->db_password = '';
}
if (empty($this->db_type)) {
$this->db_type = 'mysql';
}
if (empty($this->db_port)) {
$this->db_port = '3306';
if ($this->db_type == 'pgsql') {
$this->db_port = '5432';
}
}
if (empty($this->db_host)) {
$this->db_host = 'localhost';
}
if (empty($this->db_username)) {
$this->db_username = 'root';
}
if (empty($this->portal_name)) {
$this->portal_name = '1c portal';
}
if (empty($this->odinc_password_stud)) {
$this->odinc_password_stud = '1';
}
if (empty($this->odinc_password_abit)) {
$this->odinc_password_abit = '1';
}
if (empty($this->odinc_url)) {
$this->odinc_url = 'http://localhost/local';
}
if (empty($this->odinc_url_stud)) {
$this->odinc_url_stud = '/ws/Study.1cws?wsdl';
}
if (empty($this->odinc_url_abit)) {
$this->odinc_url_abit = '/ws/webabit.1cws?wsdl';
}
if (empty($this->odinc_login_abit)) {
$this->odinc_login_abit = 'Пользователь Web-сервис WebAbit';
}
if (empty($this->odinc_login_stud)) {
$this->odinc_login_stud = 'Пользователь Web-сервис WebStudy';
}
if (isset($this->server_type)) {
$this->server_type = (int)$this->server_type;
}
$this->rootPath = FileHelper::normalizePath(dirname(__FILE__) . '/../..');
return true;
}
public function actionIndex()
{
if ($this->check_environments) {
if (!$this->environmentsIsCorrect()) {
$this->printError('Система не удовлетворяет требованиям');
return ExitCode::UNSPECIFIED_ERROR;
}
if (!$this->foldersPermissionIsCorrect()) {
$this->printError('Система не удовлетворяет требованиям');
return ExitCode::UNSPECIFIED_ERROR;
}
}
if (!$this->setServerSettings()) {
$this->printError('Не удалось настроить конфигурацию сервера');
return ExitCode::UNSPECIFIED_ERROR;
}
if (!$this->setDataBaseSettings()) {
$this->printError('Не удалось настроить конфигурацию сервера СУБД');
return ExitCode::UNSPECIFIED_ERROR;
}
if (!$this->setEnvironment()) {
$this->printError('Не удалось настроить .env сервера');
return ExitCode::UNSPECIFIED_ERROR;
}
if (!$this->installEnding()) {
$this->printError('Не удалось завершить установку');
return ExitCode::UNSPECIFIED_ERROR;
}
return ExitCode::OK;
}
public function printNextStepNumber()
{
echo 'Шаг ' .
$this->ansiFormat('№', Console::FG_CYAN) .
$this->ansiFormat($this->stepNumber, Console::FG_YELLOW) .
"\n";
$this->stepNumber++;
}
public function actionVerify()
{
echo Table::widget([
'headers' => ['Project', 'Status'],
'rows' => [
['Portal 1C', 'OK'],
],
]);
return ExitCode::OK;
}
private function convertToBoolean($param = '', $default = false)
{
if (empty($param)) {
return $default;
}
$param = mb_strtolower($param);
if (in_array($param, self::YES_LIST)) {
return true;
} elseif (in_array($param, self::NO_LIST)) {
return false;
} else {
$this->printError('Неверно указанный параметр.');
return null;
}
}
private function printError($message = '')
{
$message = $this->ansiFormat(
$message,
Console::FG_RED
);
$this->stdout(
"Ошибка. {$message}",
Console::BOLD
);
}
private function foldersPermissionIsCorrect()
{
$this->printNextStepNumber();
$path = FileHelper::normalizePath("{$this->rootPath}/frontend/web/install/src/steps/webserver/");
require_once("{$path}/folders_requirements.php");
$folders = getFolders();
$table = [
'headers' => ['№', 'Директория', 'Права'],
'rows' => [],
];
$hasError = false;
$i = 1;
foreach ($folders as $dir => $permission) {
if ($permission) {
$status = '× некорректные права ×';
$hasError = true;
} else {
$status = '✓ права корректные ✓';
}
$table['rows'][] = [
$i,
$dir,
$status,
];
$i++;
}
echo 'Проверка ' . $this->ansiFormat('прав доступа', Console::FG_YELLOW) . "\n";
echo Table::widget($table);
$finalWord = $this->ansiFormat('СООТВЕТСТВУЮТ', Console::FG_GREEN);
if ($hasError) {
$finalWord = $this->ansiFormat('НЕ СООТВЕТСТВУЮТ', Console::FG_RED);
}
echo "Директории {$finalWord} правам доступа\n\n";
return !$hasError;
}
private function environmentsIsCorrect()
{
$this->printNextStepNumber();
$path = FileHelper::normalizePath("{$this->rootPath}/frontend/web/install/src/steps/system_requirements");
$frameworkPath = FileHelper::normalizePath("{$path}/requirements");
if (!is_dir($frameworkPath)) {
$this->printError('Невозможно найти Yii фреймворк');
return false;
}
require_once("{$path}/customs_requirements.php");
$requirementsChecker = getRequirementChecker($frameworkPath, $this->php_path);
if (empty($requirementsChecker->result['requirements'])) {
return true;
}
$table = [
'headers' => ['№', 'Результат', 'Наименование', 'Описание'],
'rows' => [],
];
$hasError = false;
foreach ($requirementsChecker->result['requirements'] as $key => $requirement) {
if ($requirement['error']) {
$status = '× ошибка ×';
$hasError = true;
} elseif ($requirement['warning']) {
$status = '! внимание !';
} else {
$status = '✓ успех ✓';
}
$memo = $requirement['memo'];
if (strlen((string)$memo) > 115) {
$memo = '-';
}
$table['rows'][] = [
$key,
$status,
$requirement['name'],
$memo,
];
}
echo 'Проверка корректности ' . $this->ansiFormat('окружения', Console::FG_YELLOW) . "\n";
echo Table::widget($table);
$finalWord = $this->ansiFormat('СООТВЕТСТВУЕТ', Console::FG_GREEN);
if ($hasError) {
$finalWord = $this->ansiFormat('НЕ СООТВЕТСТВУЕТ', Console::FG_RED);
}
echo "Окружение {$finalWord} минимальным требованиям\n\n";
return !$hasError;
}
private function setServerSettings()
{
$this->printNextStepNumber();
if (!isset($this->server_type)) {
echo "Выберите используемый веб-сервер:\n";
foreach (self::SERVERS_LIST as $number => $name) {
echo " {$number}) $name\n";
}
$this->server_type = (int)readline('');
}
$server = ArrayHelper::getValue(self::SERVERS_LIST, $this->server_type);
if (isset($server)) {
$server = $this->ansiFormat($server, Console::FG_YELLOW);
echo "Копирование конфигурации для сервера \"{$server}\"\n";
$confsPath = FileHelper::normalizePath("{$this->rootPath}/confs");
$copyResult = false;
switch ($this->server_type) {
case self::SERVER_APACHE:
copy("{$confsPath}/.htaccess", "{$this->rootPath}/.htaccess");
$copyResult = file_exists("{$this->rootPath}/.htaccess");
break;
case self::SERVER_IIS:
copy("{$confsPath}/web.config", "{$this->rootPath}/web.config");
$copyResult = file_exists("{$this->rootPath}/web.config");
break;
case self::SERVER_OTHER:
$copyResult = true;
break;
}
if ($copyResult) {
echo $this->ansiFormat("Конфигурация успешно скопирована\n\n", Console::FG_GREEN);
} else {
echo $this->ansiFormat("Произошла ошибка копирования\n\n", Console::FG_RED);
}
return $copyResult;
} else {
$errorType = $this->ansiFormat('НЕ ВЕРНЫЙ', Console::FG_RED);
echo "Выбран {$errorType} тип сервера\n\n";
}
return false;
}
private function setDataBaseSettings()
{
$this->printNextStepNumber();
if (!$this->db_silent_setup) {
$attrList = [
'db_type' => 'Тип СУБД (mysql/pgsql)',
'db_host' => 'Адрес сервера',
'db_port' => 'Порт сервера',
'db_username' => 'Имя пользователя',
'db_password' => 'Пароль',
'db_name' => 'Наименование базы данных',
];
echo "Введите параметры для подключения к серверу СУБД (значение в скобках будет задано при пропуске параметра)\n";
foreach ($attrList as $attr => $alias) {
$buffer = (string)readline(" {$alias} ({$this->{$attr}}): ");
$buffer = trim((string)$buffer);
if (!empty($buffer)) {
$this->{$attr} = $buffer;
}
}
echo "\n";
}
if (preg_match('/[^a-zA-Z0-9]+^_/', $this->db_name)) {
$this->printError('В названии БД используются недопустимый символ');
return false;
}
$serverSettings = $this->ansiFormat(
"{$this->db_type}:host={$this->db_host} port={$this->db_port} username={$this->db_username} db_name={$this->db_name}",
Console::FG_YELLOW
);
echo "Настройка сервера СУБД: \"{$serverSettings}\".\n";
$path = FileHelper::normalizePath("{$this->rootPath}/frontend/web/install/src/controllers/DatabaseController.php");
require_once($path);
$className = 'DatabaseController';
$databaseController = new $className();
$databaseController->type = $this->db_type;
$databaseController->port = $this->db_port;
$databaseController->server = $this->db_host;
$databaseController->dbname = $this->db_name;
$databaseController->username = $this->db_username;
$databaseController->password = $this->db_password;
$connectResult = $databaseController->connectToServer(false);
if ($connectResult === true) {
$useDbResult = $databaseController->useDb(false);
if ($useDbResult === true) {
$writeDsnToEnvResult = $databaseController->writeDsnToEnv('/..', false);
if ($writeDsnToEnvResult === true) {
echo $this->ansiFormat("Cервер СУБД успешно настроен\n\n", Console::FG_GREEN);
return true;
} else {
$this->printError("{$writeDsnToEnvResult}\n");
return false;
}
} else {
$this->printError("{$useDbResult}\n");
return false;
}
} else {
$this->printError("{$connectResult}\n");
}
return false;
}
private function setEnvironment()
{
$this->printNextStepNumber();
$attrList = [
'domain' => 'Домен личного кабинета',
'portal_name' => 'Имя личного кабинета',
];
echo "Введите параметры для настройки сервера (значение в скобках будет задано при пропуске параметра)\n";
foreach ($attrList as $attr => $alias) {
$buffer = (string)readline(" {$alias} ({$this->{$attr}}): ");
$buffer = trim((string)$buffer);
if (!empty($buffer)) {
$this->{$attr} = $buffer;
}
};
echo "\n";
if (!isset($this->enable_1c_services)) {
$this->enable_1c_services = $this->convertToBoolean(
readline("Включить работу с SOAP-сервисами 1С? (Y / n): \n"),
true
);
} else {
$this->enable_1c_services = $this->convertToBoolean($this->enable_1c_services, true);
}
if (!isset($this->enable_1c_services)) {
return false;
}
$path = FileHelper::normalizePath("{$this->rootPath}/frontend/web/install/src/controllers/EnvironmentController.php");
require_once($path);
$className = 'EnvironmentController';
$environmentController = new $className();
$environmentController->odinc_url = '';
$environmentController->mail_host = '';
$environmentController->mail_port = '';
$environmentController->admin_mail = '';
$environmentController->outer_mail = '';
$environmentController->mail_protocol = '';
$environmentController->mail_username = '';
$environmentController->mail_password = '';
$environmentController->odinc_url_stud = '';
$environmentController->odinc_url_abit = '';
$environmentController->odinc_login_stud = '';
$environmentController->odinc_login_abit = '';
$environmentController->odinc_password_stud = '';
$environmentController->odinc_password_abit = '';
$environmentController->domain = $this->domain;
$environmentController->portal_name = $this->portal_name;
$environmentController->enable_1c_services = $this->enable_1c_services ? 'true' : 'false';
$state = [];
if ($this->enable_1c_services) {
$attrList = [
'odinc_url' => 'Адрес публика 1С',
'odinc_url_stud' => 'Префикс адреса публикации кабинета для студента',
'odinc_url_abit' => 'Префикс адреса публикации кабинета для поступающего',
'odinc_login_stud' => 'Логин для кабинета студента',
'odinc_login_abit' => 'Логин для кабинета поступающего',
'odinc_password_stud' => 'Пароль от кабинета студента',
'odinc_password_abit' => 'Пароль от кабинета поступающего',
];
echo "Введите параметры для настройки подключения к 1С серверу (значение в скобках будет задано при пропуске параметра)\n";
foreach ($attrList as $attr => $alias) {
$buffer = (string)readline(" {$alias} ({$this->{$attr}}): ");
$buffer = trim((string)$buffer);
if (!empty($buffer)) {
$this->{$attr} = $buffer;
}
};
echo "\n";
$environmentController->odinc_url = $this->odinc_url;
$environmentController->odinc_url_stud = $this->odinc_url_stud;
$environmentController->odinc_url_abit = $this->odinc_url_abit;
$environmentController->odinc_login_stud = $this->odinc_login_stud;
$environmentController->odinc_login_abit = $this->odinc_login_abit;
$environmentController->odinc_password_stud = $this->odinc_password_stud;
$environmentController->odinc_password_abit = $this->odinc_password_abit;
$state = $environmentController->testAllConnection();
}
$messages = $environmentController->getErrorMessage($state, $this->enable_1c_services);
if (!empty($messages)) {
foreach ($messages as $message) {
$this->printError("{$message}\n");
}
return false;
}
$environmentController->setEnv('/..', false);
echo $this->ansiFormat(".env успешно сохранён\n\n", Console::FG_GREEN);
return true;
}
private function installEnding()
{
$this->printNextStepNumber();
$path = FileHelper::normalizePath("{$this->rootPath}/frontend/web/install/src/controllers/DictionaryController.php");
require_once($path);
$className = 'DictionaryController';
$dictionaryController = new $className();
echo 'Завершение установки. Копирование ' . $this->ansiFormat(".env\n", Console::FG_YELLOW);
$finishResult = $dictionaryController->finish(false);
if ($finishResult !== true) {
$this->printError("{$finishResult}\n");
return false;
}
echo $this->ansiFormat("Установка успешно завершена\n\n", Console::FG_GREEN);
return true;
}
}