View source
<?php
namespace Drupal\Core\Command;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Database\ConnectionNotDefinedException;
use Drupal\Core\Database\Database;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Extension\InfoParserDynamic;
use Drupal\Core\Site\Settings;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class InstallCommand extends Command {
protected $classLoader;
public function __construct($class_loader) {
parent::__construct('install');
$this->classLoader = $class_loader;
}
protected function configure() {
$this
->setName('install')
->setDescription('Installs a Drupal demo site. This is not meant for production and might be too simple for custom development. It is a quick and easy way to get Drupal running.')
->addArgument('install-profile', InputArgument::OPTIONAL, 'Install profile to install the site in.')
->addOption('langcode', NULL, InputOption::VALUE_OPTIONAL, 'The language to install the site in.', 'en')
->addOption('site-name', NULL, InputOption::VALUE_OPTIONAL, 'Set the site name.', 'Drupal')
->addUsage('demo_umami --langcode fr')
->addUsage('standard --site-name QuickInstall');
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output) : int {
$io = new SymfonyStyle($input, $output);
if (!extension_loaded('pdo_sqlite')) {
$io
->getErrorStyle()
->error('You must have the pdo_sqlite PHP extension installed. See core/INSTALL.sqlite.txt for instructions.');
return 1;
}
chdir(dirname(__DIR__, 5));
if ($this
->isDrupalInstalled()) {
$output
->writeln('<info>Drupal is already installed.</info> If you want to reinstall, remove sites/default/files and sites/default/settings.php.');
return 0;
}
$install_profile = $input
->getArgument('install-profile');
if ($install_profile && !$this
->validateProfile($install_profile, $io)) {
return 1;
}
if (!$install_profile) {
$install_profile = $this
->selectProfile($io);
}
return $this
->install($this->classLoader, $io, $install_profile, $input
->getOption('langcode'), $this
->getSitePath(), $input
->getOption('site-name'));
}
protected function isDrupalInstalled() {
try {
$kernel = new DrupalKernel('prod', $this->classLoader, FALSE);
$kernel::bootEnvironment();
$kernel
->setSitePath($this
->getSitePath());
Settings::initialize($kernel
->getAppRoot(), $kernel
->getSitePath(), $this->classLoader);
$kernel
->boot();
} catch (ConnectionNotDefinedException $e) {
return FALSE;
}
return !empty(Database::getConnectionInfo());
}
protected function install($class_loader, SymfonyStyle $io, $profile, $langcode, $site_path, $site_name) {
$password = Crypt::randomBytesBase64(12);
$parameters = [
'interactive' => FALSE,
'site_path' => $site_path,
'parameters' => [
'profile' => $profile,
'langcode' => $langcode,
],
'forms' => [
'install_settings_form' => [
'driver' => 'sqlite',
'sqlite' => [
'database' => $site_path . '/files/.sqlite',
],
],
'install_configure_form' => [
'site_name' => $site_name,
'site_mail' => 'drupal@localhost',
'account' => [
'name' => 'admin',
'mail' => 'admin@localhost',
'pass' => [
'pass1' => $password,
'pass2' => $password,
],
],
'enable_update_status_module' => TRUE,
'enable_update_status_emails' => NULL,
],
],
];
if (!is_dir($site_path)) {
if ($io
->isVerbose()) {
$io
->writeln("Creating directory: {$site_path}");
}
if (!mkdir($site_path, 0775)) {
throw new \RuntimeException("Failed to create directory {$site_path}");
}
}
if (!file_exists("{$site_path}/settings.php")) {
if ($io
->isVerbose()) {
$io
->writeln("Creating file: {$site_path}/settings.php");
}
if (!copy('sites/default/default.settings.php', "{$site_path}/settings.php")) {
throw new \RuntimeException("Copying sites/default/default.settings.php to {$site_path}/settings.php failed.");
}
}
require_once 'core/includes/install.core.inc';
$progress_bar = $io
->createProgressBar();
install_drupal($class_loader, $parameters, function ($install_state) use ($progress_bar) {
static $started = FALSE;
if (!$started) {
$started = TRUE;
$progress_bar
->setFormat("%current%/%max% [%bar%]\n%message%\n");
$progress_bar
->setMessage(t('Installing @drupal', [
'@drupal' => drupal_install_profile_distribution_name(),
]));
$tasks = install_tasks($install_state);
$progress_bar
->start(count($tasks) + 1);
}
$tasks_to_perform = install_tasks_to_perform($install_state);
$task = current($tasks_to_perform);
if (isset($task['display_name'])) {
$progress_bar
->setMessage($task['display_name']);
}
$progress_bar
->advance();
});
$success_message = t('Congratulations, you installed @drupal!', [
'@drupal' => drupal_install_profile_distribution_name(),
'@name' => 'admin',
'@pass' => $password,
], [
'langcode' => $langcode,
]);
$progress_bar
->setMessage('<info>' . $success_message . '</info>');
$progress_bar
->display();
$progress_bar
->finish();
$io
->writeln('<info>Username:</info> admin');
$io
->writeln("<info>Password:</info> {$password}");
return 0;
}
protected function getSitePath() {
return getenv('DRUPAL_DEV_SITE_PATH') ?: 'sites/default';
}
protected function selectProfile(SymfonyStyle $io) {
$profiles = $this
->getProfiles();
if (count($profiles) == 1) {
return key($profiles);
}
natcasesort($profiles);
if (isset($profiles['minimal'])) {
$profiles = [
'minimal' => $profiles['minimal'],
] + $profiles;
}
if (isset($profiles['standard'])) {
$profiles = [
'standard' => $profiles['standard'],
] + $profiles;
}
reset($profiles);
return $io
->choice('Select an installation profile', $profiles, current($profiles));
}
protected function validateProfile($install_profile, SymfonyStyle $io) {
$profiles = $this
->getProfiles(TRUE, FALSE);
if (!isset($profiles[$install_profile])) {
$error_msg = sprintf("'%s' is not a valid install profile.", $install_profile);
$alternatives = [];
foreach (array_keys($profiles) as $profile_name) {
$lev = levenshtein($install_profile, $profile_name);
if ($lev <= strlen($profile_name) / 4 || str_contains($profile_name, $install_profile)) {
$alternatives[] = $profile_name;
}
}
if (!empty($alternatives)) {
$error_msg .= sprintf(" Did you mean '%s'?", implode("' or '", $alternatives));
}
$io
->getErrorStyle()
->error($error_msg);
return FALSE;
}
return TRUE;
}
protected function getProfiles($include_hidden = FALSE, $auto_select_distributions = TRUE) {
$listing = new ExtensionDiscovery(getcwd(), FALSE);
$listing
->setProfileDirectories([]);
$profiles = [];
$info_parser = new InfoParserDynamic(getcwd());
foreach ($listing
->scan('profile') as $profile) {
$details = $info_parser
->parse($profile
->getPathname());
if (!$include_hidden && !empty($details['hidden'])) {
continue;
}
$name = $details['name'] ?? $profile
->getName();
$description = $details['description'] ?? $name;
$profiles[$profile
->getName()] = $description;
if ($auto_select_distributions && !empty($details['distribution'])) {
return [
$profile
->getName() => $description,
];
}
}
return $profiles;
}
}