Files
apart-moment/core/lib/Thelia/Command/Install.php
2021-03-23 13:54:38 +01:00

346 lines
11 KiB
PHP

<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Filesystem\Filesystem;
use Thelia\Core\Translation\Translator;
use Thelia\Install\CheckPermission;
use Thelia\Install\Database;
use Thelia\Tools\TokenProvider;
/**
* try to install a new instance of Thelia
*
* Class Install
* @package Thelia\Command
* @author Manuel Raynaud <manu@raynaud.io>
*/
class Install extends ContainerAwareCommand
{
/**
* Configure the command
*/
protected function configure()
{
$this
->setName("thelia:install")
->setDescription("Install thelia using cli tools. For now Thelia only use mysql database")
->setHelp("The <info>thelia:install</info> command install Thelia database and create config file needed.")
->addOption(
"db_host",
null,
InputOption::VALUE_OPTIONAL,
"host for your database",
"localhost"
)
->addOption(
"db_username",
null,
InputOption::VALUE_OPTIONAL,
"username for your database"
)
->addOption(
"db_password",
null,
InputOption::VALUE_OPTIONAL,
"password for your database"
)
->addOption(
"db_name",
null,
InputOption::VALUE_OPTIONAL,
"database name"
)
->addOption(
"db_port",
null,
InputOption::VALUE_OPTIONAL,
"database port",
"3306"
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln(array(
'',
'Welcome to Thelia install process',
'You need information about your database configuration (host, username, password, database name, etc)',
'',
'<info>Caution : You are installing Thelia in cli mode, we verify some information, but this information are only available for the cli php sapi</info>',
'<info>This informations can be different in your apache or cgi php.ini files</info>',
''
));
$this->checkPermission($output);
$connectionInfo = array(
"host" => $input->getOption("db_host"),
"dbName" => $input->getOption("db_name"),
"username" => $input->getOption("db_username"),
"password" => $input->getOption("db_password"),
"port" => $input->getOption("db_port")
);
while (false === $connection = $this->tryConnection($connectionInfo, $output)) {
$connectionInfo = $this->getConnectionInfo($input, $output);
}
$database = new Database($connection);
$database->createDatabase($connectionInfo["dbName"]);
$output->writeln(array(
"",
"<info>Creating Thelia database, please wait</info>",
""
));
$database->insertSql($connectionInfo["dbName"]);
$this->manageSecret($database);
$output->writeln(array(
"",
"<info>Database created without errors</info>",
"<info>Creating file configuration, please wait</info>",
""
));
$this->createConfigFile($connectionInfo);
$output->writeln(array(
"",
"<info>Config file created with success. Your thelia is installed</info>",
""
));
}
protected function manageSecret(Database $database)
{
$secret = TokenProvider::generateToken();
$sql = "UPDATE `config` SET `value`=? WHERE `name`='form.secret'";
$database->execute($sql, [$secret]);
}
/**
* Test if needed directories have write permission
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
*/
protected function checkPermission(OutputInterface $output)
{
$output->writeln(array(
"Checking some permissions"
));
/** @var Translator $translator */
$translator = $this->getContainer()->get('thelia.translator');
$permissions = new CheckPermission(false, $translator);
$isValid = $permissions->exec();
foreach ($permissions->getValidationMessages() as $item => $data) {
if ($data['status']) {
$output->writeln(
array(
sprintf(
"<info>%s ...</info> %s",
$data['text'],
"<info>Ok</info>"
)
)
);
} else {
$output->writeln(array(
sprintf(
"<error>%s </error>%s",
$data['text'],
sprintf("<error>%s</error>", $data["hint"])
)
));
}
}
if (false === $isValid) {
throw new \RuntimeException('Please put correct permissions and reload install process');
}
}
/**
* rename database config file and complete it
*
* @param array $connectionInfo
*/
protected function createConfigFile($connectionInfo)
{
$fs = new Filesystem();
$sampleConfigFile = THELIA_CONF_DIR . "database.yml.sample";
$configFile = THELIA_CONF_DIR . "database.yml";
$fs->copy($sampleConfigFile, $configFile, true);
$configContent = file_get_contents($configFile);
$configContent = str_replace("%DRIVER%", "mysql", $configContent);
$configContent = str_replace("%USERNAME%", $connectionInfo["username"], $configContent);
$configContent = str_replace("%PASSWORD%", $connectionInfo["password"], $configContent);
$configContent = str_replace(
"%DSN%",
sprintf("mysql:host=%s;dbname=%s;port=%s", $connectionInfo["host"], $connectionInfo["dbName"], $connectionInfo['port']),
$configContent
);
file_put_contents($configFile, $configContent);
$fs->remove($this->getContainer()->getParameter("kernel.cache_dir"));
}
/**
* test database access
*
* @param $connectionInfo
* @param OutputInterface $output
* @return bool|\PDO
*/
protected function tryConnection($connectionInfo, OutputInterface $output)
{
if (is_null($connectionInfo["dbName"])) {
return false;
}
$dsn = "mysql:host=%s;port=%s";
try {
$connection = new \PDO(
sprintf($dsn, $connectionInfo["host"], $connectionInfo["port"]),
$connectionInfo["username"],
$connectionInfo["password"]
);
$connection->query('SET NAMES \'UTF8\'');
} catch (\PDOException $e) {
$output->writeln(array(
"<error>Wrong connection information</error>"
));
return false;
}
return $connection;
}
/**
* Ask to user all needed information
*
* @param InputInterface $input
* @param OutputInterface $output
* @return array
*/
protected function getConnectionInfo(InputInterface $input, OutputInterface $output)
{
/** @var QuestionHelper $helper */
$helper = $this->getHelper('question');
$connectionInfo = array();
$connectionInfo['host'] = $this->enterData(
$helper,
$input,
$output,
"Database host [default: localhost] : ",
"You must specify a database host",
false,
"localhost"
);
$connectionInfo['port'] = $this->enterData(
$helper,
$input,
$output,
"Database port [default: 3306] : ",
"You must specify a database port",
false,
"3306"
);
$connectionInfo['dbName'] = $this->enterData(
$helper,
$input,
$output,
"Database name (if database does not exist, Thelia will try to create it) : ",
"You must specify a database name"
);
$connectionInfo['username'] = $this->enterData(
$helper,
$input,
$output,
"Database username : ",
"You must specify a database username"
);
$connectionInfo['password'] = $this->enterData(
$helper,
$input,
$output,
"Database password : ",
"You must specify a database username",
true,
null,
true
);
return $connectionInfo;
}
protected function enterData(
QuestionHelper $helper,
InputInterface $input,
OutputInterface $output,
$label,
$errorMessage,
$hidden = false,
$defaultValue = null,
$beEmpty = false
) {
$question = new Question($label, $defaultValue);
if ($hidden) {
$question->setHidden(true);
$question->setHiddenFallback(false);
}
$question->setValidator(function ($value) use (&$errorMessage, &$beEmpty) {
if (trim($value) == '') {
if (is_null($value) && !$beEmpty) {
throw new \Exception($errorMessage);
}
}
return $value;
});
return $helper->ask($input, $output, $question);
}
protected function decorateInfo($text)
{
return sprintf("<info>%s</info>", $text);
}
}