Skip to content

Commit

Permalink
Move getBootOptions (etc) from BaseApplication to BootTrait
Browse files Browse the repository at this point in the history
  • Loading branch information
totten committed Sep 24, 2024
1 parent 25cb9d8 commit d01fa84
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 22 deletions.
2 changes: 1 addition & 1 deletion lib/src/BaseApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected function getDefaultInputDefinition() {
$c = new class() {
use BootTrait;
};
$c->configureDefinition($definition);
$c->mergeDefaultBootDefinition($definition);

return $definition;
}
Expand Down
22 changes: 2 additions & 20 deletions lib/src/Command/BaseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,17 @@ class BaseCommand extends Command {
use OptionCallbackTrait;
use BootTrait;

public function getBootOptions(): array {
return [
'auto' => TRUE,
'default' => 'full|cms-full',
'allow' => ['full|cms-full', 'full', 'cms-full', 'settings', 'classloader', 'cms-only', 'none'],
];
}

public function mergeApplicationDefinition($mergeArgs = TRUE) {
parent::mergeApplicationDefinition($mergeArgs);
$bootOptions = $this->getBootOptions();
$this->getDefinition()->getOption('level')->setDefault($bootOptions['default']);
$this->mergeBootDefinition($this->getDefinition());
}

/**
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
*/
protected function initialize(InputInterface $input, OutputInterface $output) {
$bootOptions = $this->getBootOptions();
if (!in_array($input->getOption('level'), $bootOptions['allow'])) {
throw new \LogicException(sprintf("Command called with with level (%s) but only accepts levels (%s)",
$input->getOption('level'), implode(', ', $bootOptions['allow'])));
}

if (!$this->isBooted() && ($bootOptions['auto'] ?? TRUE)) {
$this->boot($input, $output);
}

$this->autoboot($input, $output);
parent::initialize($input, $output);
$this->runOptionCallbacks($input, $output);
}
Expand Down
72 changes: 71 additions & 1 deletion lib/src/Util/BootTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,70 @@
*/
trait BootTrait {

/**
* Describe the expected bootstrap behaviors for this command.
*
* - For most commands, you will want to automatically boot CiviCRM/CMS.
* The default implementation will do this.
* - For some special commands (e.g. core-installer or PHP-script-runner), you may
* want more fine-grained control over when/how the system boots.
*
* @var array
*/
protected $bootOptions = [
// Whether to automatically boot Civi during `initialize()` phase.
'auto' => TRUE,

// Default boot level.
'default' => 'full|cms-full',

// List of all boot levels that are allowed in this command.
'allow' => ['full|cms-full', 'full', 'cms-full', 'settings', 'classloader', 'cms-only', 'none'],
];

/**
* @internal
*/
public function configureDefinition($definition, $defaultLevel = 'full|cms-full') {
public function mergeDefaultBootDefinition($definition, $defaultLevel = 'full|cms-full') {
// If we were only dealing with built-in/global commands, then these options could be defined at the command-level.
// However, we also have extension-based commands. The system will boot before we have a chance to discover them.
// By putting these options at the application level, we ensure they will be defined+used.
$definition->addOption(new InputOption('level', NULL, InputOption::VALUE_REQUIRED, 'Bootstrap level (none,classloader,settings,full,cms-only,cms-full)', $defaultLevel));
$definition->addOption(new InputOption('hostname', NULL, InputOption::VALUE_REQUIRED, 'Hostname (for a multisite system)'));
$definition->addOption(new InputOption('test', 't', InputOption::VALUE_NONE, 'Bootstrap the test database (CIVICRM_UF=UnitTests)'));
$definition->addOption(new InputOption('user', 'U', InputOption::VALUE_REQUIRED, 'CMS user'));
}

/**
* @internal
*/
public function mergeBootDefinition($definition) {
$bootOptions = $this->getBootOptions();
$definition->getOption('level')->setDefault($bootOptions['default']);
}

/**
* Evaluate the $bootOptions.
*
* - If we've already booted, do nothing.
* - If the configuration looks reasonable and if we haven't booted yet, then boot().
* - If the configuration looks unreasonable, then abort.
*/
protected function autoboot(InputInterface $input, OutputInterface $output): void {
$bootOptions = $this->getBootOptions();
if (!in_array($input->getOption('level'), $bootOptions['allow'])) {
throw new \LogicException(sprintf("Command called with with level (%s) but only accepts levels (%s)",
$input->getOption('level'), implode(', ', $bootOptions['allow'])));
}

if (!$this->isBooted() && ($bootOptions['auto'] ?? TRUE)) {
$this->boot($input, $output);
}
}

/**
* Start CiviCRM and/or CMS. Respect options like --user and --level.
*/
public function boot(InputInterface $input, OutputInterface $output) {
$logger = $this->bootLogger($output);
$logger->debug('Start');
Expand Down Expand Up @@ -306,4 +360,20 @@ protected function assertBooted() {
}
}

/**
* @return array{auto: bool, default: string, allow: string[]}
*/
public function getBootOptions(): array {
return $this->bootOptions;
}

/**
* @param array{auto: bool, default: string, allow: string[]} $bootOptions
* @return $this
*/
public function setBootOptions(array $bootOptions) {
$this->bootOptions = $bootOptions;
return $this;
}

}

0 comments on commit d01fa84

Please sign in to comment.