Skip to content

Commit

Permalink
Improve bootstrap / initialization of the site:install method (#5576)
Browse files Browse the repository at this point in the history
* Add a "createEarly" method

* Use isAbstract instead of isInstantiable; do not allow module commands to use "createEarly".

* Remove AwareInterfaces from site install command. Note that it still inherits ConfigAwareInterface from DrushCommands.

* Update comments in inflect method

* Add typehint to instantiateServices

Co-authored-by: Moshe Weitzman <weitzman@tejasa.com>

* Fix typo: commandInstances

---------

Co-authored-by: Moshe Weitzman <weitzman@tejasa.com>
  • Loading branch information
greg-1-anderson and weitzman authored May 20, 2023
1 parent e3e8450 commit 4477f45
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 47 deletions.
9 changes: 8 additions & 1 deletion src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Consolidation\AnnotatedCommand\AnnotatedCommand;
use Consolidation\SiteAlias\SiteAliasManager;
use Drush\Boot\BootstrapManager;
use Drush\Drush;
use Drush\Boot\DrupalBootLevels;
use Drush\Command\RemoteCommandProxy;
use Drush\Config\ConfigAwareTrait;
Expand Down Expand Up @@ -327,8 +328,14 @@ public function configureAndRegisterCommands(InputInterface $input, OutputInterf
// unset($commandClasses[__DIR__ . '/Commands/help/HelpCommands.php']);
// unset($commandClasses[__DIR__ . '/Commands/help/ListCommands.php']);

// Instantiate our command handler objects with the service manager
// (handles 'createEarly' static factories)
$commandInstances = $this->serviceManager->instantiateServices($commandClasses, Drush::getContainer());

// Register our commands with Robo, our application framework.
Robo::register($this, $commandClasses);
// Note that Robo::register can accept either Annotated Command
// command handlers or Symfony Console Command objects.
Robo::register($this, $commandInstances);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Boot/BootstrapManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ public function logger(): ?LoggerInterface
return $this->logger;
}

// TODO: This is moving to the ServiceManager class. We'll remove
// it here after cleaning up the bootstrap a bit.
public function inflect($object): void
{
// See \Drush\Runtime\DependencyInjection::addDrushServices and
Expand Down
5 changes: 2 additions & 3 deletions src/Boot/DrupalBoot8.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ public function addDrupalModuleDrushCommands(BootstrapManager $manager): void

// Find the command info alterers in Drush services.
$commandFactory = Drush::commandFactory();
$commandInfoAltererInstances = $this->serviceManager->instantiateServices($commandInfoAlterers, $container, $drushContainer);
$commandInfoAltererInstances = $this->serviceManager->instantiateServices($commandInfoAlterers, $drushContainer, $container);
$commandInfoAlterers = array_merge($commandInfoAltererInstances, $legacyServiceInstantiator->taggedServices('drush.command_info_alterer'));

// Set the command info alterers. We must do this prior to calling
Expand Down Expand Up @@ -317,11 +317,10 @@ public function addDrupalModuleDrushCommands(BootstrapManager $manager): void
// Instantiate all of the classes we discovered in
// configureAndRegisterCommands, and all of the classes we find
// via 'discoverModuleCommands' that have static create factory methods.
$commandHandlers = $this->serviceManager->instantiateServices($bootstrapCommandClasses, $container, $drushContainer);
$commandHandlers = $this->serviceManager->instantiateServices($bootstrapCommandClasses, $drushContainer, $container);

// Inflect and register all command handlers
foreach ($commandHandlers as $commandHandler) {
$manager->inflect($commandHandler);
Robo::register($application, $commandHandler);
}
}
Expand Down
54 changes: 33 additions & 21 deletions src/Commands/core/SiteInstallCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,41 @@
use Drush\Boot\DrupalBootLevels;
use Drush\Boot\Kernels;
use Drush\Commands\DrushCommands;
use Drush\Config\ConfigAwareTrait;
use Drush\Drush;
use Drush\Exceptions\UserAbortException;
use Drupal\Core\Config\FileStorage;
use Consolidation\SiteAlias\SiteAliasManagerAwareInterface;
use Consolidation\SiteAlias\SiteAliasManagerAwareTrait;
use Drush\Exec\ExecTrait;
use Drush\Sql\SqlBase;
use Drush\Utils\StringUtils;
use Robo\Contract\ConfigAwareInterface;
use Psr\Container\ContainerInterface as DrushContainer;
use Symfony\Component\Filesystem\Path;
use Drush\Boot\BootstrapManager;
use Consolidation\SiteAlias\SiteAliasManager;
use Drush\Config\DrushConfig;

final class SiteInstallCommands extends DrushCommands implements SiteAliasManagerAwareInterface, ConfigAwareInterface
final class SiteInstallCommands extends DrushCommands
{
use ConfigAwareTrait;
use ExecTrait;
use SiteAliasManagerAwareTrait;

const INSTALL = 'site:install';

public function __construct(
private BootstrapManager $bootstrapManager,
private SiteAliasManager $siteAliasManager
) {
parent::__construct();
}

public static function createEarly(DrushContainer $drush_container): self
{
$commandHandler = new static(
$drush_container->get('bootstrap.manager'),
$drush_container->get('site.alias.manager')
);

return $commandHandler;
}

/**
* Install Drupal along with modules/themes/configuration/profile.
*/
Expand Down Expand Up @@ -78,8 +93,8 @@ public function install(array $profile, $options = ['db-url' => self::REQ, 'db-p
$form_options[$key] = $value;
}

$this->serverGlobals(Drush::bootstrapManager()->getUri());
$class_loader = Drush::service('loader');
$this->serverGlobals($this->bootstrapManager->getUri());
$class_loader = $this->bootstrapManager->autoloader();
$profile = $this->determineProfile($profile, $options, $class_loader);

$account_pass = $options['account-pass'] ?: StringUtils::generatePassword();
Expand Down Expand Up @@ -185,7 +200,7 @@ protected function determineProfile($profile, $options, $class_loader)
}

if (empty($profile)) {
$boot = Drush::bootstrap();
$boot = $this->bootstrapManager->bootstrap();
$profile = $boot->getKernel()->getInstallProfile();
}

Expand Down Expand Up @@ -228,15 +243,14 @@ protected function hasConfigFiles($config): bool
#[CLI\Hook(type: HookManager::ARGUMENT_VALIDATOR, target: self::INSTALL)]
public function validate(CommandData $commandData): void
{
$bootstrapManager = Drush::bootstrapManager();
if ($sites_subdir = $commandData->input()->getOption('sites-subdir')) {
$lower = strtolower($sites_subdir);
if ($sites_subdir != $lower) {
$this->logger()->warning(dt('Only lowercase sites-subdir are valid. Switching to !lower.', ['!lower' => $lower]));
$commandData->input()->setOption('sites-subdir', $lower);
}
// Make sure that we will bootstrap to the 'sites-subdir' site.
$bootstrapManager->setUri('http://' . $sites_subdir);
$this->bootstrapManager->setUri('http://' . $sites_subdir);
}

if ($config = $commandData->input()->getOption('config-dir')) {
Expand All @@ -245,11 +259,11 @@ public function validate(CommandData $commandData): void

try {
// Try to get any already configured database information.
$bootstrapManager->bootstrapMax(DrupalBootLevels::CONFIGURATION, $commandData->annotationData());
$this->bootstrapManager->bootstrapMax(DrupalBootLevels::CONFIGURATION, $commandData->annotationData());

// See https://github.com/drush-ops/drush/issues/3903.
// We may have bootstrapped with /default/settings.php instead of the sites-subdir one.
if ($sites_subdir && "sites/$sites_subdir" !== $bootstrapManager->bootstrap()->confpath()) {
if ($sites_subdir && "sites/$sites_subdir" !== $this->bootstrapManager->bootstrap()->confpath()) {
Database::removeConnection('default');
}
} catch (\Exception) {
Expand Down Expand Up @@ -288,7 +302,7 @@ public function pre(CommandData $commandData): void

// This command is 'bootstrap root', so we should always have a
// Drupal root. If we do not, $aliasRecord->root will throw.
$aliasRecord = $this->siteAliasManager()->getSelf();
$aliasRecord = $this->siteAliasManager->getSelf();
$root = $aliasRecord->root();

$dir = $commandData->input()->getOption('sites-subdir');
Expand Down Expand Up @@ -334,37 +348,35 @@ public function pre(CommandData $commandData): void
$this->io()->listing($msg);
}


if (!$this->io()->confirm(dt('Do you want to continue?'))) {
throw new UserAbortException();
}

// Can't install without sites subdirectory and settings.php.
if (!file_exists($confPath)) {
if ((new \Symfony\Component\Filesystem\Filesystem())->mkdir($confPath) && !$this->getConfig()->simulate()) {
if ((new \Symfony\Component\Filesystem\Filesystem())->mkdir($confPath) && !$this->config->simulate()) {
throw new \Exception(dt('Failed to create directory @confPath', ['@confPath' => $confPath]));
}
} else {
$this->logger()->info(dt('Sites directory @subdir already exists - proceeding.', ['@subdir' => $confPath]));
}

if (!drush_file_not_empty($settingsfile)) {
if (!drush_op('copy', 'sites/default/default.settings.php', $settingsfile) && !$this->getConfig()->simulate()) {
if (!drush_op('copy', 'sites/default/default.settings.php', $settingsfile) && !$this->config->simulate()) {
throw new \Exception(dt('Failed to copy sites/default/default.settings.php to @settingsfile', ['@settingsfile' => $settingsfile]));
}
}

// Write an empty sites.php if we using multi-site.
if ($sitesfile_write) {
if (!drush_op('copy', 'sites/example.sites.php', $sitesfile) && !$this->getConfig()->simulate()) {
if (!drush_op('copy', 'sites/example.sites.php', $sitesfile) && !$this->config->simulate()) {
throw new \Exception(dt('Failed to copy sites/example.sites.php to @sitesfile', ['@sitesfile' => $sitesfile]));
}
}

// We need to be at least at DRUSH_BOOTSTRAP_DRUPAL_SITE to select the site uri to install to
define('MAINTENANCE_MODE', 'install');
$bootstrapManager = Drush::bootstrapManager();
$bootstrapManager->doBootstrap(DrupalBootLevels::SITE);
$this->bootstrapManager->doBootstrap(DrupalBootLevels::SITE);

if ($program_exists && !$sql->dropOrCreate()) {
$this->logger()->warning(dt('Failed to drop or create the database. Do it yourself before installing. @error', ['@error' => $sql->getProcess()->getErrorOutput()]));
Expand Down
7 changes: 3 additions & 4 deletions src/Runtime/DependencyInjection.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,12 @@ protected function addDrushServices($container, ClassLoader $loader, DrushDrupal
// Add some of our own objects to the container
Robo::addShared($container, 'service.manager', 'Drush\Runtime\ServiceManager')
->addArgument('loader')
->addMethodCall('setConfig', ['config']);
->addArgument('config')
->addArgument('logger');
Robo::addShared($container, 'bootstrap.drupal8', 'Drush\Boot\DrupalBoot8')
->addArgument('service.manager');
Robo::addShared($container, 'bootstrap.manager', 'Drush\Boot\BootstrapManager')
->addMethodCall('setDrupalFinder', [$drupalFinder]);
// TODO: Can we somehow add these via discovery (e.g. backdrop extension?)
$container->extend('bootstrap.manager')
->addMethodCall('setDrupalFinder', [$drupalFinder])
->addMethodCall('add', ['bootstrap.drupal8']);
Robo::addShared($container, 'bootstrap.hook', 'Drush\Boot\BootstrapHook')
->addArgument('bootstrap.manager');
Expand Down
Loading

0 comments on commit 4477f45

Please sign in to comment.