From 0d25b40502d1bc167942dc19ee1491b362a58d8a Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 11:44:02 -0700 Subject: [PATCH 01/16] (REF) Move `isBooted()`, `assertBooted()` from `BaseCommand` to `BootTrait` --- lib/src/Util/BootTrait.php | 13 +++++++++++++ src/Command/BaseCommand.php | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/src/Util/BootTrait.php b/lib/src/Util/BootTrait.php index c3baf46f..47ed62f4 100644 --- a/lib/src/Util/BootTrait.php +++ b/lib/src/Util/BootTrait.php @@ -290,4 +290,17 @@ private function bootLogger(OutputInterface $output): InternalLogger { return new SymfonyConsoleLogger('BootTrait', $output); } + /** + * @return bool + */ + protected function isBooted() { + return defined('CIVICRM_DSN'); + } + + protected function assertBooted() { + if (!$this->isBooted()) { + throw new \Exception("Error: This command requires bootstrapping, but the system does not appear to be bootstrapped. Perhaps you set --level=none?"); + } + } + } diff --git a/src/Command/BaseCommand.php b/src/Command/BaseCommand.php index 2647d191..168218e5 100644 --- a/src/Command/BaseCommand.php +++ b/src/Command/BaseCommand.php @@ -20,12 +20,6 @@ protected function initialize(InputInterface $input, OutputInterface $output) { $this->runOptionCallbacks($input, $output); } - protected function assertBooted() { - if (!$this->isBooted()) { - throw new \Exception("Error: This command requires bootstrapping, but the system does not appear to be bootstrapped. Perhaps you set --level=none?"); - } - } - /** * Execute an API call. If it fails, display a formatted error. * @@ -101,11 +95,4 @@ public function parseOptionalOption(InputInterface $input, $rawNames, $omittedDe return $omittedDefault; } - /** - * @return bool - */ - protected function isBooted() { - return defined('CIVICRM_DSN'); - } - } From e04f655e62ad153f4a085cdaec18089a13cb19b6 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 12:06:20 -0700 Subject: [PATCH 02/16] (REF) Move BaseCommand::parseOptionalOption() to OptionalOption::parse() --- lib/src/Util/OptionalOption.php | 42 +++++++++++++++++ src/Command/BaseCommand.php | 35 -------------- src/Command/CoreInstallCommand.php | 3 +- src/Command/CoreUninstallCommand.php | 3 +- src/Command/ExtensionEnableCommand.php | 2 +- src/Util/StructuredOutputTrait.php | 4 +- tests/Command/BaseCommandTest.php | 50 -------------------- tests/Util/OptionalOptionTest.php | 65 ++++++++++++++++++++++++++ 8 files changed, 114 insertions(+), 90 deletions(-) create mode 100644 lib/src/Util/OptionalOption.php delete mode 100644 tests/Command/BaseCommandTest.php create mode 100644 tests/Util/OptionalOptionTest.php diff --git a/lib/src/Util/OptionalOption.php b/lib/src/Util/OptionalOption.php new file mode 100644 index 00000000..38bf8c92 --- /dev/null +++ b/lib/src/Util/OptionalOption.php @@ -0,0 +1,42 @@ + Means "--refresh=auto"; see $omittedDefault + * cv en -r ==> Means "--refresh=yes"; see $activeDefault + * cv en -r=yes ==> Means "--refresh=yes" + * cv en -r=no ==> Means "--refresh=no" + * + * @param \CvDeps\Symfony\Component\Console\Input\InputInterface|\Symfony\Component\Console\Input\InputInterface $input + * @param array $rawNames + * Ex: array('-r', '--refresh'). + * @param string $omittedDefault + * Value to use if option is completely omitted. + * @param string $activeDefault + * Value to use if option is activated without data. + * @return string + */ + public static function parse($input, $rawNames, $omittedDefault, $activeDefault) { + $value = NULL; + foreach ($rawNames as $rawName) { + if ($input->hasParameterOption($rawName)) { + if (NULL === $input->getParameterOption($rawName)) { + return $activeDefault; + } + else { + return $input->getParameterOption($rawName); + } + } + } + return $omittedDefault; + } + +} diff --git a/src/Command/BaseCommand.php b/src/Command/BaseCommand.php index 168218e5..c0b698fc 100644 --- a/src/Command/BaseCommand.php +++ b/src/Command/BaseCommand.php @@ -60,39 +60,4 @@ protected function callApiSuccess(InputInterface $input, OutputInterface $output return $result; } - /** - * Parse an option's data. This is for options where the default behavior - * (of total omission) differs from the activated behavior - * (of an active but unspecified option). - * - * Example, suppose we want these interpretations: - * cv en ==> Means "--refresh=auto"; see $omittedDefault - * cv en -r ==> Means "--refresh=yes"; see $activeDefault - * cv en -r=yes ==> Means "--refresh=yes" - * cv en -r=no ==> Means "--refresh=no" - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param array $rawNames - * Ex: array('-r', '--refresh'). - * @param string $omittedDefault - * Value to use if option is completely omitted. - * @param string $activeDefault - * Value to use if option is activated without data. - * @return string - */ - public function parseOptionalOption(InputInterface $input, $rawNames, $omittedDefault, $activeDefault) { - $value = NULL; - foreach ($rawNames as $rawName) { - if ($input->hasParameterOption($rawName)) { - if (NULL === $input->getParameterOption($rawName)) { - return $activeDefault; - } - else { - return $input->getParameterOption($rawName); - } - } - } - return $omittedDefault; - } - } diff --git a/src/Command/CoreInstallCommand.php b/src/Command/CoreInstallCommand.php index 76166030..f4c38cd0 100644 --- a/src/Command/CoreInstallCommand.php +++ b/src/Command/CoreInstallCommand.php @@ -2,6 +2,7 @@ namespace Civi\Cv\Command; use Civi\Cv\Encoder; +use Civi\Cv\Util\OptionalOption; use Civi\Cv\Util\SetupCommandTrait; use Civi\Cv\Util\DebugDispatcherTrait; use Symfony\Component\Console\Input\InputInterface; @@ -57,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $debugMode = FALSE; - $debugEvent = $this->parseOptionalOption($input, ['--debug-event'], NULL, ''); + $debugEvent = OptionalOption::parse($input, ['--debug-event'], NULL, ''); if ($debugEvent !== NULL) { $eventNames = $this->findEventNames($setup->getDispatcher(), $debugEvent); $this->printEventListeners($output, $setup->getDispatcher(), $eventNames); diff --git a/src/Command/CoreUninstallCommand.php b/src/Command/CoreUninstallCommand.php index d6563fca..343db33f 100644 --- a/src/Command/CoreUninstallCommand.php +++ b/src/Command/CoreUninstallCommand.php @@ -1,6 +1,7 @@ bootSetupSubsystem($input, $output); - $debugEvent = $this->parseOptionalOption($input, ['--debug-event'], NULL, ''); + $debugEvent = OptionalOption::parse($input, ['--debug-event'], NULL, ''); if ($debugEvent !== NULL) { $eventNames = $this->findEventNames($setup->getDispatcher(), $debugEvent); $this->printEventListeners($output, $setup->getDispatcher(), $eventNames); diff --git a/src/Command/ExtensionEnableCommand.php b/src/Command/ExtensionEnableCommand.php index 0de3bba5..0d57f90f 100644 --- a/src/Command/ExtensionEnableCommand.php +++ b/src/Command/ExtensionEnableCommand.php @@ -45,7 +45,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int // Refresh extensions if (a) ---refresh enabled or (b) there's a cache-miss. $refresh = $input->getOption('refresh') ? 'yes' : 'auto'; - // $refresh = $this->parseOptionalOption($input, array('--refresh', '-r'), 'auto', 'yes'); + // $refresh = OptionalOption::parse(array('--refresh', '-r'), 'auto', 'yes'); while (TRUE) { if ($refresh === 'yes') { $output->writeln("Refreshing extension cache"); diff --git a/src/Util/StructuredOutputTrait.php b/src/Util/StructuredOutputTrait.php index f9fd553e..66064542 100644 --- a/src/Util/StructuredOutputTrait.php +++ b/src/Util/StructuredOutputTrait.php @@ -113,7 +113,7 @@ protected function configureOutputOptions($config = []) { * @see Encoder::getFormats */ protected function sendResult(InputInterface $input, OutputInterface $output, $result) { - $flat = $this->parseOptionalOption($input, ['--flat'], FALSE, '.'); + $flat = OptionalOption::parse($input, ['--flat'], FALSE, '.'); if ($flat !== FALSE) { $result = ArrayUtil::implodeTree($flat, $result); } @@ -157,7 +157,7 @@ protected function sendTable(InputInterface $input, OutputInterface $output, $re return; } - $flat = $this->parseOptionalOption($input, ['--flat'], FALSE, '.'); + $flat = OptionalOption::parse($input, ['--flat'], FALSE, '.'); if ($flat !== FALSE) { $filtered = ArrayUtil::filterColumns($records, $columns); $flattened = ArrayUtil::implodeTree($flat, $filtered); diff --git a/tests/Command/BaseCommandTest.php b/tests/Command/BaseCommandTest.php deleted file mode 100644 index 808b5a0e..00000000 --- a/tests/Command/BaseCommandTest.php +++ /dev/null @@ -1,50 +0,0 @@ -addOption('refresh', array('r'), InputOption::VALUE_OPTIONAL, 'auto'); - - $input = new ArgvInput($inputArgv, $c->getDefinition()); - $this->assertEquals($expectValue, $c->parseOptionalOption($input, array('-r', '--refresh'), 'auto', 'yes')); - } - -} diff --git a/tests/Util/OptionalOptionTest.php b/tests/Util/OptionalOptionTest.php new file mode 100644 index 00000000..2f8f9c0b --- /dev/null +++ b/tests/Util/OptionalOptionTest.php @@ -0,0 +1,65 @@ +push(...$this->createInputOutput($inputArgv)); + try { + $this->assertEquals($expectValue, OptionalOption::parse(Cv::input(), ['-r', '--refresh'], 'auto', 'yes')); + } + finally { + Cv::ioStack()->pop(); + } + } + + /** + * @return array + * [0 => InputInterface, 1 => OutputInterface] + */ + protected function createInputOutput(array $argv = NULL): array { + $input = new ArgvInput($argv); + $input->setInteractive(FALSE); + $output = new NullOutput(); + return [$input, $output]; + } + +} From 35aa90d02b6469dc9bc3794c17e75aeb89703e1c Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 12:27:46 -0700 Subject: [PATCH 03/16] (REF) Move BaseCommand::callApiSuccess() to VerboseApi::callApi3Success() --- src/Command/BaseCommand.php | 41 -------------------- src/Command/ExtensionDisableCommand.php | 5 ++- src/Command/ExtensionDownloadCommand.php | 11 +++--- src/Command/ExtensionEnableCommand.php | 7 ++-- src/Command/ExtensionListCommand.php | 7 ++-- src/Command/ExtensionUninstallCommand.php | 7 ++-- src/Command/ExtensionUpgradeDbCommand.php | 3 +- src/Command/FlushCommand.php | 3 +- src/Util/VerboseApi.php | 47 +++++++++++++++++++++++ 9 files changed, 72 insertions(+), 59 deletions(-) create mode 100644 src/Util/VerboseApi.php diff --git a/src/Command/BaseCommand.php b/src/Command/BaseCommand.php index c0b698fc..99ca6681 100644 --- a/src/Command/BaseCommand.php +++ b/src/Command/BaseCommand.php @@ -1,7 +1,6 @@ runOptionCallbacks($input, $output); } - /** - * Execute an API call. If it fails, display a formatted error. - * - * Note: If there is an error, we still return it softly so that the - * command can exit gracefully. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @param $entity - * @param $action - * @param $params - * @return mixed - */ - protected function callApiSuccess(InputInterface $input, OutputInterface $output, $entity, $action, $params) { - $this->assertBooted(); - $params['debug'] = 1; - if (!isset($params['version'])) { - $params['version'] = 3; - } - $output->writeln("Calling $entity $action API", OutputInterface::VERBOSITY_DEBUG); - $result = \civicrm_api($entity, $action, $params); - if (!empty($result['is_error']) || $output->isDebug()) { - $data = array( - 'entity' => $entity, - 'action' => $action, - 'params' => $params, - 'result' => $result, - ); - if (!empty($result['is_error'])) { - $output->getErrorOutput()->writeln("Error: API Call Failed: " - . Encoder::encode($data, 'pretty')); - } - else { - $output->writeln("API success" . Encoder::encode($data, 'pretty'), - OutputInterface::VERBOSITY_DEBUG); - } - } - return $result; - } - } diff --git a/src/Command/ExtensionDisableCommand.php b/src/Command/ExtensionDisableCommand.php index abc058a3..c5991d03 100644 --- a/src/Command/ExtensionDisableCommand.php +++ b/src/Command/ExtensionDisableCommand.php @@ -1,6 +1,7 @@ boot($input, $output); - list ($foundKeys, $missingKeys) = $this->parseKeys($input, $output); + [$foundKeys, $missingKeys] = $this->parseKeys($input, $output); // Uninstall what's recognized or what looks like an ext key. $disableKeys = array_merge($foundKeys, preg_grep('/\./', $missingKeys)); @@ -52,7 +53,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln("Disabling extension \"$key\""); } - $result = $this->callApiSuccess($input, $output, 'Extension', 'disable', array( + $result = VerboseApi::callApi3Success('Extension', 'disable', array( 'keys' => $disableKeys, )); return empty($result['is_error']) ? 0 : 1; diff --git a/src/Command/ExtensionDownloadCommand.php b/src/Command/ExtensionDownloadCommand.php index f5820af6..cb62a723 100644 --- a/src/Command/ExtensionDownloadCommand.php +++ b/src/Command/ExtensionDownloadCommand.php @@ -3,6 +3,7 @@ use Civi\Cv\Util\Filesystem; use Civi\Cv\Util\HeadlessDownloader; +use Civi\Cv\Util\VerboseApi; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -91,7 +92,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int while (TRUE) { if ($refresh === 'yes' && $this->isBooted()) { $output->writeln("Refreshing extension cache"); - $result = $this->callApiSuccess($input, $output, 'Extension', 'refresh', array( + $result = VerboseApi::callApi3Success('Extension', 'refresh', array( 'local' => FALSE, 'remote' => TRUE, )); @@ -100,7 +101,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } - list ($downloads, $errors) = $this->parseDownloads($input); + [$downloads, $errors] = $this->parseDownloads($input); if ($refresh == 'auto' && !empty($errors)) { $output->writeln("Extension cache does not contain requested item(s)"); $refresh = 'yes'; @@ -135,7 +136,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int else { $output->writeln("Downloading extension \"$key\" ($url)"); $this->assertBooted(); - $result = $this->callApiSuccess($input, $output, 'Extension', 'download', array( + $result = VerboseApi::callApi3Success('Extension', 'download', array( 'key' => $key, 'url' => $url, 'install' => !$input->getOption('no-install'), @@ -145,7 +146,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int case 'install': $output->writeln("Found extension \"$key\". Enabling."); - $result = $this->callApiSuccess($input, $output, 'Extension', 'enable', array( + $result = VerboseApi::callApi3Success('Extension', 'enable', array( 'key' => $key, )); break; @@ -225,7 +226,7 @@ protected function parseDownloads(InputInterface $input) { $origExpr = $keyOrName; $url = NULL; if (strpos($keyOrName, '@') !== FALSE) { - list ($keyOrName, $url) = explode('@', $keyOrName, 2); + [$keyOrName, $url] = explode('@', $keyOrName, 2); } if (empty($keyOrName) && !empty($url)) { diff --git a/src/Command/ExtensionEnableCommand.php b/src/Command/ExtensionEnableCommand.php index 0d57f90f..201cba29 100644 --- a/src/Command/ExtensionEnableCommand.php +++ b/src/Command/ExtensionEnableCommand.php @@ -1,6 +1,7 @@ writeln("Refreshing extension cache"); - $result = $this->callApiSuccess($input, $output, 'Extension', 'refresh', array( + $result = VerboseApi::callApi3Success('Extension', 'refresh', array( 'local' => TRUE, 'remote' => FALSE, )); @@ -58,7 +59,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } - list ($foundKeys, $missingKeys) = $this->parseKeys($input, $output); + [$foundKeys, $missingKeys] = $this->parseKeys($input, $output); if ($refresh == 'auto' && !empty($missingKeys)) { $output->writeln("Extension cache does not contain requested item(s)"); $refresh = 'yes'; @@ -87,7 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln("Enabling extension \"$key\""); } - $result = $this->callApiSuccess($input, $output, 'Extension', 'install', array( + $result = VerboseApi::callApi3Success('Extension', 'install', array( 'keys' => $foundKeys, )); return empty($result['is_error']) ? 0 : 1; diff --git a/src/Command/ExtensionListCommand.php b/src/Command/ExtensionListCommand.php index b5577451..a26475d6 100644 --- a/src/Command/ExtensionListCommand.php +++ b/src/Command/ExtensionListCommand.php @@ -5,6 +5,7 @@ use Civi\Cv\Util\ArrayUtil; use Civi\Cv\Util\Relativizer; use Civi\Cv\Util\StructuredOutputTrait; +use Civi\Cv\Util\VerboseApi; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -82,7 +83,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ? (OutputInterface::OUTPUT_NORMAL | OutputInterface::VERBOSITY_NORMAL) : (OutputInterface::OUTPUT_NORMAL | OutputInterface::VERBOSITY_VERBOSE); - list($local, $remote) = $this->parseLocalRemote($input); + [$local, $remote] = $this->parseLocalRemote($input); if ($extRepoUrl = $this->parseRepoUrl($input)) { global $civicrm_setting; @@ -97,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($input->getOption('refresh')) { $output->writeln("Refreshing extensions", $wo); - $result = $this->callApiSuccess($input, $output, 'Extension', 'refresh', array( + $result = VerboseApi::callApi3Success('Extension', 'refresh', array( 'local' => $local, 'remote' => $remote, )); @@ -136,7 +137,7 @@ protected function getRemoteInfos() { */ protected function find($input) { $regex = $input->getArgument('regex'); - list($local, $remote) = $this->parseLocalRemote($input); + [$local, $remote] = $this->parseLocalRemote($input); if ($input->getOption('installed')) { $statusFilter = array('installed'); diff --git a/src/Command/ExtensionUninstallCommand.php b/src/Command/ExtensionUninstallCommand.php index 839ab593..3a740713 100644 --- a/src/Command/ExtensionUninstallCommand.php +++ b/src/Command/ExtensionUninstallCommand.php @@ -1,6 +1,7 @@ boot($input, $output); - list ($foundKeys, $missingKeys) = $this->parseKeys($input, $output); + [$foundKeys, $missingKeys] = $this->parseKeys($input, $output); // Uninstall what's recognized or what looks like an ext key. $uninstallKeys = array_merge($foundKeys, preg_grep('/\./', $missingKeys)); @@ -52,14 +53,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln("Uninstalling extension \"$key\""); } - $result = $this->callApiSuccess($input, $output, 'Extension', 'disable', array( + $result = VerboseApi::callApi3Success('Extension', 'disable', array( 'keys' => $uninstallKeys, )); if (!empty($result['is_error'])) { return 1; } - $result = $this->callApiSuccess($input, $output, 'Extension', 'uninstall', array( + $result = VerboseApi::callApi3Success('Extension', 'uninstall', array( 'keys' => $uninstallKeys, )); return empty($result['is_error']) ? 0 : 1; diff --git a/src/Command/ExtensionUpgradeDbCommand.php b/src/Command/ExtensionUpgradeDbCommand.php index 41f87295..da593d84 100644 --- a/src/Command/ExtensionUpgradeDbCommand.php +++ b/src/Command/ExtensionUpgradeDbCommand.php @@ -1,6 +1,7 @@ boot($input, $output); $output->writeln("Applying database upgrades from extensions"); - $result = $this->callApiSuccess($input, $output, 'Extension', 'upgrade', array()); + $result = VerboseApi::callApi3Success('Extension', 'upgrade', array()); if (!empty($result['is_error'])) { return 1; } diff --git a/src/Command/FlushCommand.php b/src/Command/FlushCommand.php index b522a90a..e6db6843 100644 --- a/src/Command/FlushCommand.php +++ b/src/Command/FlushCommand.php @@ -2,6 +2,7 @@ namespace Civi\Cv\Command; use Civi\Cv\Util\BootTrait; +use Civi\Cv\Util\VerboseApi; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -34,7 +35,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $output->writeln("Flushing system caches"); - $result = $this->callApiSuccess($input, $output, 'System', 'flush', $params); + $result = VerboseApi::callApi3Success('System', 'flush', $params); return empty($result['is_error']) ? 0 : 1; } diff --git a/src/Util/VerboseApi.php b/src/Util/VerboseApi.php new file mode 100644 index 00000000..475e774b --- /dev/null +++ b/src/Util/VerboseApi.php @@ -0,0 +1,47 @@ +writeln("Calling $entity $action API", OutputInterface::VERBOSITY_DEBUG); + $result = \civicrm_api($entity, $action, $params); + if (!empty($result['is_error']) || $output->isDebug()) { + $data = array( + 'entity' => $entity, + 'action' => $action, + 'params' => $params, + 'result' => $result, + ); + if (!empty($result['is_error'])) { + $output->getErrorOutput()->writeln("Error: API Call Failed: " + . Encoder::encode($data, 'pretty')); + } + else { + $output->writeln("API success" . Encoder::encode($data, 'pretty'), + OutputInterface::VERBOSITY_DEBUG); + } + } + return $result; + } + +} From a32eb359c005498766681ba244f9887beb2f48e2 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 12:33:20 -0700 Subject: [PATCH 04/16] (NFC) OptionCallbackTrait --- src/Util/OptionCallbackTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Util/OptionCallbackTrait.php b/src/Util/OptionCallbackTrait.php index 0b7742e4..7295faf9 100644 --- a/src/Util/OptionCallbackTrait.php +++ b/src/Util/OptionCallbackTrait.php @@ -33,6 +33,7 @@ abstract public function getDefinition(); * @param string $name * The name of the option to * @param callable $callback + * Function(InputInterface $input, OutputInterface, $output, string $optionName) * @return $this */ public function addOptionCallback($name, $callback) { From 22e9a820cb51876fcb2ab91c629bdd7f9eb48b9f Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 13:17:31 -0700 Subject: [PATCH 05/16] Track active $application. Convert BaseApplication::__construct() to BaseApplication::configure() This is a semantic change to how BaseApplication is initialized. However, I don't believe anyone else is using this yet, so it's academic. --- lib/src/BaseApplication.php | 5 +++-- lib/src/Cv.php | 7 +++++++ lib/src/Util/IOStack.php | 9 ++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/src/BaseApplication.php b/lib/src/BaseApplication.php index 9c4c668f..2f51677a 100644 --- a/lib/src/BaseApplication.php +++ b/lib/src/BaseApplication.php @@ -24,6 +24,8 @@ public static function main(string $name, ?string $binDir, array $argv) { try { $application = new static($name); + Cv::ioStack()->replace('app', $application); + $application->configure(); $argv = AliasFilter::filter($argv); $result = $application->run(new CvArgvInput($argv), Cv::ioStack()->current('output')); } @@ -38,8 +40,7 @@ public static function main(string $name, ?string $binDir, array $argv) { exit($result); } - public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') { - parent::__construct($name, $version); + public function configure() { $this->setCatchExceptions(TRUE); $this->setAutoExit(FALSE); diff --git a/lib/src/Cv.php b/lib/src/Cv.php index bb5e4915..26e30db9 100644 --- a/lib/src/Cv.php +++ b/lib/src/Cv.php @@ -79,6 +79,13 @@ public static function ioStack(): IOStack { return static::$instances[__FUNCTION__]; } + /** + * @return \CvDeps\Symfony\Component\Console\Application|\Symfony\Component\Console\Application + */ + public static function app() { + return static::ioStack()->current('app'); + } + /** * @return \CvDeps\Symfony\Component\Console\Input\InputInterface|\Symfony\Component\Console\Input\InputInterface */ diff --git a/lib/src/Util/IOStack.php b/lib/src/Util/IOStack.php index 08f85e56..a8e734b1 100644 --- a/lib/src/Util/IOStack.php +++ b/lib/src/Util/IOStack.php @@ -21,16 +21,19 @@ class IOStack { * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output + * @param \Symfony\Component\Console\Application|null $app * @return scalar * Internal identifier for the stack-frame. ID formatting is not guaranteed. */ - public function push(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface $output) { + public function push(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface $output, ?\Symfony\Component\Console\Application $app = NULL) { ++static::$id; + $app = $app ?: ($this->stack[0]['app'] ?? NULL); array_unshift($this->stack, [ 'id' => static::$id, 'input' => $input, 'output' => $output, 'io' => new SymfonyStyle($input, $output), + 'app' => $app, ]); return static::$id; } @@ -68,6 +71,10 @@ public function get($id, string $property) { return NULL; } + public function replace($property, $value) { + $this->stack[0][$property] = $value; + } + public function reset() { $this->stack = []; } From 8c52475ff025578afb7c654f2fe8171a61fac015 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 21:58:20 -0700 Subject: [PATCH 06/16] Don't explicitly call BootTrait, configureBootOptions --- src/Command/AngularHtmlListCommand.php | 3 --- src/Command/AngularHtmlShowCommand.php | 4 ---- src/Command/AngularModuleListCommand.php | 3 --- src/Command/Api4Command.php | 3 --- src/Command/ApiBatchCommand.php | 4 ---- src/Command/ApiCommand.php | 3 --- src/Command/BaseExtensionCommand.php | 3 --- src/Command/BootCommand.php | 4 ---- src/Command/CliCommand.php | 4 ---- src/Command/CoreCheckReqCommand.php | 5 ++++- src/Command/CoreInstallCommand.php | 5 ++++- src/Command/CoreUninstallCommand.php | 5 ++++- src/Command/DebugContainerCommand.php | 3 --- src/Command/DebugDispatcherCommand.php | 3 --- src/Command/EditCommand.php | 4 ---- src/Command/EvalCommand.php | 3 --- src/Command/ExtensionDisableCommand.php | 1 - src/Command/ExtensionDownloadCommand.php | 1 - src/Command/ExtensionEnableCommand.php | 1 - src/Command/ExtensionListCommand.php | 1 - src/Command/ExtensionUninstallCommand.php | 1 - src/Command/ExtensionUpgradeDbCommand.php | 1 - src/Command/FillCommand.php | 4 ---- src/Command/FlushCommand.php | 4 ---- src/Command/HttpCommand.php | 1 - src/Command/PathCommand.php | 1 - src/Command/PipeCommand.php | 5 ----- src/Command/ScriptCommand.php | 4 ---- src/Command/SettingGetCommand.php | 3 --- src/Command/SettingRevertCommand.php | 3 --- src/Command/SettingSetCommand.php | 3 --- src/Command/ShowCommand.php | 3 --- src/Command/SqlCliCommand.php | 4 ---- src/Command/UpgradeDbCommand.php | 3 --- src/Command/UpgradeGetCommand.php | 3 --- src/Command/UrlCommand.php | 1 - src/Util/SetupCommandTrait.php | 1 - 37 files changed, 12 insertions(+), 96 deletions(-) diff --git a/src/Command/AngularHtmlListCommand.php b/src/Command/AngularHtmlListCommand.php index b191577e..d0713348 100644 --- a/src/Command/AngularHtmlListCommand.php +++ b/src/Command/AngularHtmlListCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/AngularHtmlShowCommand.php b/src/Command/AngularHtmlShowCommand.php index 41801d2c..9114b5ae 100644 --- a/src/Command/AngularHtmlShowCommand.php +++ b/src/Command/AngularHtmlShowCommand.php @@ -2,7 +2,6 @@ namespace Civi\Cv\Command; use Civi\Cv\Util\Process; -use Civi\Cv\Util\BootTrait; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -10,8 +9,6 @@ class AngularHtmlShowCommand extends BaseCommand { - use BootTrait; - /** * @param string|null $name */ @@ -38,7 +35,6 @@ protected function configure() { cv ang:html:show crmMailing/BlockMailing.html --diff | colordiff cv ang:html:show "~/crmMailing/BlockMailing.html" '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/AngularModuleListCommand.php b/src/Command/AngularModuleListCommand.php index 5bc51f57..925018d4 100644 --- a/src/Command/AngularModuleListCommand.php +++ b/src/Command/AngularModuleListCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/Api4Command.php b/src/Command/Api4Command.php index 1c796304..4a3668ba 100644 --- a/src/Command/Api4Command.php +++ b/src/Command/Api4Command.php @@ -3,7 +3,6 @@ use Civi\Cv\Encoder; use Civi\Cv\Util\Api4ArgParser; -use Civi\Cv\Util\BootTrait; use Civi\Cv\Util\StructuredOutputTrait; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -12,7 +11,6 @@ class Api4Command extends BaseCommand { - use BootTrait; use StructuredOutputTrait; /** @@ -122,7 +120,6 @@ protected function configure() { NOTE: To change the default output format, set CV_OUTPUT. "); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ApiBatchCommand.php b/src/Command/ApiBatchCommand.php index 59d9ad9d..c8a4c3e7 100644 --- a/src/Command/ApiBatchCommand.php +++ b/src/Command/ApiBatchCommand.php @@ -1,15 +1,12 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ApiCommand.php b/src/Command/ApiCommand.php index 14e15e72..4ceb348b 100644 --- a/src/Command/ApiCommand.php +++ b/src/Command/ApiCommand.php @@ -2,7 +2,6 @@ namespace Civi\Cv\Command; use Civi\Cv\Encoder; -use Civi\Cv\Util\BootTrait; use Civi\Cv\Util\StructuredOutputTrait; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -11,7 +10,6 @@ class ApiCommand extends BaseCommand { - use BootTrait; use StructuredOutputTrait; /** @@ -47,7 +45,6 @@ protected function configure() { TIP: To display a full backtrace of any errors, pass "-vv" (very verbose). '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/BaseExtensionCommand.php b/src/Command/BaseExtensionCommand.php index efab304d..78a567b5 100644 --- a/src/Command/BaseExtensionCommand.php +++ b/src/Command/BaseExtensionCommand.php @@ -1,15 +1,12 @@ setName('php:boot') ->setDescription('Generate PHP bootstrap code'); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/CliCommand.php b/src/Command/CliCommand.php index 9dca5f27..789c2d5c 100644 --- a/src/Command/CliCommand.php +++ b/src/Command/CliCommand.php @@ -6,19 +6,15 @@ // ********************** use Civi\Cv\Application; -use Civi\Cv\Util\BootTrait; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class CliCommand extends BaseCommand { - use BootTrait; - protected function configure() { $this ->setName('cli') ->setDescription('Load interactive command line'); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/CoreCheckReqCommand.php b/src/Command/CoreCheckReqCommand.php index d9836efc..8a1cedc4 100644 --- a/src/Command/CoreCheckReqCommand.php +++ b/src/Command/CoreCheckReqCommand.php @@ -35,7 +35,10 @@ protected function configure() { Example: Show warnings and errors $ cv core:check-req -we '); - $this->configureBootOptions('none'); + } + + public function getBootOptions(): array { + return ['default' => 'none', 'allow' => ['none']]; } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/CoreInstallCommand.php b/src/Command/CoreInstallCommand.php index f4c38cd0..5649932d 100644 --- a/src/Command/CoreInstallCommand.php +++ b/src/Command/CoreInstallCommand.php @@ -50,7 +50,10 @@ protected function configure() { $ cv core:install --model=extras.opt-in.versionCheck=1 $ cv core:install -m extras.opt-in.versionCheck=1 '); - $this->configureBootOptions('none'); + } + + public function getBootOptions(): array { + return ['default' => 'none', 'allow' => ['none']]; } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/CoreUninstallCommand.php b/src/Command/CoreUninstallCommand.php index 343db33f..f8c4dbdd 100644 --- a/src/Command/CoreUninstallCommand.php +++ b/src/Command/CoreUninstallCommand.php @@ -29,7 +29,10 @@ protected function configure() { TIP: If you have a special system configuration, it may help to pass the same options for "core:uninstall" as the preceding "core:install". '); - $this->configureBootOptions('none'); + } + + public function getBootOptions(): array { + return ['default' => 'none', 'allow' => ['none']]; } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/DebugContainerCommand.php b/src/Command/DebugContainerCommand.php index 2d2fba3b..4f9a63ef 100644 --- a/src/Command/DebugContainerCommand.php +++ b/src/Command/DebugContainerCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/DebugDispatcherCommand.php b/src/Command/DebugDispatcherCommand.php index 1bbb6192..c094c672 100644 --- a/src/Command/DebugDispatcherCommand.php +++ b/src/Command/DebugDispatcherCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/EditCommand.php b/src/Command/EditCommand.php index 6e5f3549..7b9a3274 100644 --- a/src/Command/EditCommand.php +++ b/src/Command/EditCommand.php @@ -9,14 +9,11 @@ use Civi\Cv\Config; use Civi\Cv\Encoder; use Civi\Cv\Util\CliEditor; -use Civi\Cv\Util\BootTrait; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class EditCommand extends BaseCommand { - use BootTrait; - /** * @var \Civi\Cv\Util\CliEditor */ @@ -26,7 +23,6 @@ protected function configure() { $this ->setName('vars:edit') ->setDescription('Edit configuration values for this build'); - $this->configureBootOptions(); } public function __construct($name = NULL) { diff --git a/src/Command/EvalCommand.php b/src/Command/EvalCommand.php index 69e9d0fb..4cb8e4d6 100644 --- a/src/Command/EvalCommand.php +++ b/src/Command/EvalCommand.php @@ -2,7 +2,6 @@ namespace Civi\Cv\Command; use Civi\Cv\Encoder; -use Civi\Cv\Util\BootTrait; use Civi\Cv\Util\StructuredOutputTrait; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -10,7 +9,6 @@ class EvalCommand extends BaseCommand { - use BootTrait; use StructuredOutputTrait; protected function configure() { @@ -37,7 +35,6 @@ protected function configure() { NOTE: To change the default output format, set CV_OUTPUT. '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ExtensionDisableCommand.php b/src/Command/ExtensionDisableCommand.php index c5991d03..b5ad7b71 100644 --- a/src/Command/ExtensionDisableCommand.php +++ b/src/Command/ExtensionDisableCommand.php @@ -35,7 +35,6 @@ protected function configure() { This subcommand does not output parseable data. For parseable output, consider using `cv api extension.disable`. '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ExtensionDownloadCommand.php b/src/Command/ExtensionDownloadCommand.php index cb62a723..1921db30 100644 --- a/src/Command/ExtensionDownloadCommand.php +++ b/src/Command/ExtensionDownloadCommand.php @@ -58,7 +58,6 @@ protected function configure() { consider using `cv api extension.install`. '); parent::configureRepoOptions(); - $this->configureBootOptions(); } protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/src/Command/ExtensionEnableCommand.php b/src/Command/ExtensionEnableCommand.php index 201cba29..26f57957 100644 --- a/src/Command/ExtensionEnableCommand.php +++ b/src/Command/ExtensionEnableCommand.php @@ -38,7 +38,6 @@ protected function configure() { This subcommand does not output parseable data. For parseable output, consider using `cv api extension.install`. '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ExtensionListCommand.php b/src/Command/ExtensionListCommand.php index a26475d6..78dcc6b5 100644 --- a/src/Command/ExtensionListCommand.php +++ b/src/Command/ExtensionListCommand.php @@ -58,7 +58,6 @@ protected function configure() { name ("foobar"). However, short names are not strongly guaranteed. '); parent::configureRepoOptions(); - $this->configureBootOptions(); } protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/src/Command/ExtensionUninstallCommand.php b/src/Command/ExtensionUninstallCommand.php index 3a740713..a90dc948 100644 --- a/src/Command/ExtensionUninstallCommand.php +++ b/src/Command/ExtensionUninstallCommand.php @@ -35,7 +35,6 @@ protected function configure() { This subcommand does not output parseable data. For parseable output, consider using `cv api extension.uninstall`. '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ExtensionUpgradeDbCommand.php b/src/Command/ExtensionUpgradeDbCommand.php index da593d84..07539111 100644 --- a/src/Command/ExtensionUpgradeDbCommand.php +++ b/src/Command/ExtensionUpgradeDbCommand.php @@ -32,7 +32,6 @@ protected function configure() { This command is now deprecated. Use "cv upgrade:db" to perform upgrades for core and/or extensions. '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/FillCommand.php b/src/Command/FillCommand.php index fb332d27..cc62263a 100644 --- a/src/Command/FillCommand.php +++ b/src/Command/FillCommand.php @@ -4,15 +4,12 @@ use Civi\Cv\Config; use Civi\Cv\Encoder; use Civi\Cv\SiteConfigReader; -use Civi\Cv\Util\BootTrait; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class FillCommand extends BaseCommand { - use BootTrait; - protected $fields; /** @@ -25,7 +22,6 @@ protected function configure() { ->setName('vars:fill') ->setDescription('Generate a configuration file for any missing site data') ->addOption('file', NULL, InputOption::VALUE_REQUIRED, 'Read existing configuration from a file'); - $this->configureBootOptions(); } public function __construct($name = NULL) { diff --git a/src/Command/FlushCommand.php b/src/Command/FlushCommand.php index e6db6843..f0aab4f8 100644 --- a/src/Command/FlushCommand.php +++ b/src/Command/FlushCommand.php @@ -1,7 +1,6 @@ setName('flush') @@ -20,7 +17,6 @@ protected function configure() { ->setHelp(' Flush system caches '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/HttpCommand.php b/src/Command/HttpCommand.php index c79b78ce..af44f2e5 100644 --- a/src/Command/HttpCommand.php +++ b/src/Command/HttpCommand.php @@ -43,7 +43,6 @@ protected function configure() { enabling the extension. The extra I/O may influence some scripted use-cases. '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/PathCommand.php b/src/Command/PathCommand.php index 20348d85..183e16d3 100644 --- a/src/Command/PathCommand.php +++ b/src/Command/PathCommand.php @@ -55,7 +55,6 @@ protected function configure() { Example: Lookup multiple items cv path -x cividiscount/info.xml -x flexmailer/info.xml -d \'[civicrm.root]/civicrm-version.php\' '); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/PipeCommand.php b/src/Command/PipeCommand.php index 25d4140f..8668d683 100644 --- a/src/Command/PipeCommand.php +++ b/src/Command/PipeCommand.php @@ -1,15 +1,12 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ScriptCommand.php b/src/Command/ScriptCommand.php index 08e58f01..21943788 100644 --- a/src/Command/ScriptCommand.php +++ b/src/Command/ScriptCommand.php @@ -2,15 +2,12 @@ namespace Civi\Cv\Command; use Civi\Cv\Util\Filesystem; -use Civi\Cv\Util\BootTrait; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class ScriptCommand extends BaseCommand { - use BootTrait; - protected function configure() { $this ->setName('php:script') @@ -18,7 +15,6 @@ protected function configure() { ->setDescription('Execute a PHP script') ->addArgument('script', InputArgument::REQUIRED) ->addArgument('scriptArguments', InputArgument::IS_ARRAY, 'Optional arguments to pass to the script as $argv'); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/SettingGetCommand.php b/src/Command/SettingGetCommand.php index 36cbe2c7..a2cd4e03 100644 --- a/src/Command/SettingGetCommand.php +++ b/src/Command/SettingGetCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/SettingRevertCommand.php b/src/Command/SettingRevertCommand.php index 489a3e92..3a6cdd86 100644 --- a/src/Command/SettingRevertCommand.php +++ b/src/Command/SettingRevertCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/SettingSetCommand.php b/src/Command/SettingSetCommand.php index 4db84c66..f3620019 100644 --- a/src/Command/SettingSetCommand.php +++ b/src/Command/SettingSetCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/ShowCommand.php b/src/Command/ShowCommand.php index a598aa2f..2a6ce619 100644 --- a/src/Command/ShowCommand.php +++ b/src/Command/ShowCommand.php @@ -2,14 +2,12 @@ namespace Civi\Cv\Command; use Civi\Cv\SiteConfigReader; -use Civi\Cv\Util\BootTrait; use Civi\Cv\Util\StructuredOutputTrait; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class ShowCommand extends BaseCommand { - use BootTrait; use StructuredOutputTrait; protected function configure() { @@ -17,7 +15,6 @@ protected function configure() { ->setName('vars:show') ->setDescription('Show the configuration of the local CiviCRM installation') ->configureOutputOptions(); - $this->configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/SqlCliCommand.php b/src/Command/SqlCliCommand.php index f43b259b..9bd993e4 100644 --- a/src/Command/SqlCliCommand.php +++ b/src/Command/SqlCliCommand.php @@ -3,15 +3,12 @@ use Civi\Cv\Util\Datasource; use Civi\Cv\Util\Process; -use Civi\Cv\Util\BootTrait; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class SqlCliCommand extends BaseCommand { - use BootTrait; - protected function configure() { $this ->setName('sql') @@ -38,7 +35,6 @@ protected function configure() { #ENV[FOO] Produces the numerical value of FOO (or fails) !ENV[FOO] Produces the raw, unescaped string version of FOO "); - $this->configureBootOptions(); } protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/src/Command/UpgradeDbCommand.php b/src/Command/UpgradeDbCommand.php index c1f98f89..7b5386d3 100644 --- a/src/Command/UpgradeDbCommand.php +++ b/src/Command/UpgradeDbCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } /** diff --git a/src/Command/UpgradeGetCommand.php b/src/Command/UpgradeGetCommand.php index 56f358a3..a8f87d10 100644 --- a/src/Command/UpgradeGetCommand.php +++ b/src/Command/UpgradeGetCommand.php @@ -1,7 +1,6 @@ configureBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/UrlCommand.php b/src/Command/UrlCommand.php index b712836a..2ce822a0 100644 --- a/src/Command/UrlCommand.php +++ b/src/Command/UrlCommand.php @@ -66,7 +66,6 @@ protected function configure() { enabling the extension. The extra I/O may influence some scripted use-cases. '); - $this->configureBootOptions(); } protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/src/Util/SetupCommandTrait.php b/src/Util/SetupCommandTrait.php index 6126be06..e7022d0a 100644 --- a/src/Util/SetupCommandTrait.php +++ b/src/Util/SetupCommandTrait.php @@ -15,7 +15,6 @@ * civicrm-setup framework. */ trait SetupCommandTrait { - use BootTrait; /** * Register any CLI options which affect the initialization of the From 5c7f9a6c1aeab0a91558fe2a3231d3e0060e0300 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 23:03:01 -0700 Subject: [PATCH 07/16] Promote boot options from BootTrait to BaseApplication --- lib/src/BaseApplication.php | 7 +++++++ lib/src/Util/BootTrait.php | 13 ++++++++----- src/Command/BaseCommand.php | 25 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/src/BaseApplication.php b/lib/src/BaseApplication.php index 2f51677a..d93d0b5e 100644 --- a/lib/src/BaseApplication.php +++ b/lib/src/BaseApplication.php @@ -2,6 +2,7 @@ namespace Civi\Cv; use Civi\Cv\Util\AliasFilter; +use Civi\Cv\Util\BootTrait; use Civi\Cv\Util\CvArgvInput; use LesserEvil\ShellVerbosityIsEvil; use Symfony\Component\Console\Input\InputInterface; @@ -67,6 +68,12 @@ protected function getDefaultInputDefinition() { $definition = parent::getDefaultInputDefinition(); $definition->addOption(new InputOption('cwd', NULL, InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.')); $definition->addOption(new InputOption('site-alias', NULL, InputOption::VALUE_REQUIRED, 'Load site connection data based on its alias')); + + $c = new class() { + use BootTrait; + }; + $c->configureDefinition($definition); + return $definition; } diff --git a/lib/src/Util/BootTrait.php b/lib/src/Util/BootTrait.php index 47ed62f4..70360f67 100644 --- a/lib/src/Util/BootTrait.php +++ b/lib/src/Util/BootTrait.php @@ -16,11 +16,14 @@ */ trait BootTrait { - public function configureBootOptions($defaultLevel = 'full|cms-full') { - $this->addOption('level', NULL, InputOption::VALUE_REQUIRED, 'Bootstrap level (none,classloader,settings,full,cms-only,cms-full)', $defaultLevel); - $this->addOption('hostname', NULL, InputOption::VALUE_REQUIRED, 'Hostname (for a multisite system)'); - $this->addOption('test', 't', InputOption::VALUE_NONE, 'Bootstrap the test database (CIVICRM_UF=UnitTests)'); - $this->addOption('user', 'U', InputOption::VALUE_REQUIRED, 'CMS user'); + /** + * @internal + */ + public function configureDefinition($definition, $defaultLevel = 'full|cms-full') { + $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')); } public function boot(InputInterface $input, OutputInterface $output) { diff --git a/src/Command/BaseCommand.php b/src/Command/BaseCommand.php index 99ca6681..7f352a07 100644 --- a/src/Command/BaseCommand.php +++ b/src/Command/BaseCommand.php @@ -1,6 +1,7 @@ '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']); + } /** * @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); + } + parent::initialize($input, $output); $this->runOptionCallbacks($input, $output); } From ae1ed440417b93076aa1e34b7fdc1f4978b33188 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 00:28:24 -0700 Subject: [PATCH 08/16] Don't explicitly call boot() --- src/Command/AngularHtmlListCommand.php | 1 - src/Command/AngularHtmlShowCommand.php | 1 - src/Command/AngularModuleListCommand.php | 1 - src/Command/Api4Command.php | 2 -- src/Command/ApiBatchCommand.php | 1 - src/Command/ApiCommand.php | 2 -- src/Command/BootCommand.php | 2 -- src/Command/CliCommand.php | 2 -- src/Command/DebugContainerCommand.php | 6 ++++-- src/Command/DebugDispatcherCommand.php | 6 ++++-- src/Command/EditCommand.php | 2 -- src/Command/EvalCommand.php | 2 -- src/Command/ExtensionDisableCommand.php | 1 - src/Command/ExtensionDownloadCommand.php | 11 ++++------- src/Command/ExtensionEnableCommand.php | 2 -- src/Command/ExtensionListCommand.php | 12 +++++------- src/Command/ExtensionUninstallCommand.php | 1 - src/Command/ExtensionUpgradeDbCommand.php | 6 ++++-- src/Command/FillCommand.php | 1 - src/Command/FlushCommand.php | 7 ++++++- src/Command/HttpCommand.php | 2 -- src/Command/PathCommand.php | 2 -- src/Command/PipeCommand.php | 1 - src/Command/ScriptCommand.php | 4 ++++ src/Command/SettingGetCommand.php | 2 -- src/Command/SettingRevertCommand.php | 1 - src/Command/SettingSetCommand.php | 1 - src/Command/ShowCommand.php | 1 - src/Command/SqlCliCommand.php | 2 -- src/Command/UpgradeDbCommand.php | 8 +++----- src/Command/UpgradeGetCommand.php | 4 ++++ src/Command/UrlCommand.php | 9 +++------ 32 files changed, 41 insertions(+), 65 deletions(-) diff --git a/src/Command/AngularHtmlListCommand.php b/src/Command/AngularHtmlListCommand.php index d0713348..84657424 100644 --- a/src/Command/AngularHtmlListCommand.php +++ b/src/Command/AngularHtmlListCommand.php @@ -35,7 +35,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); if (!$input->getOption('user')) { $output->getErrorOutput()->writeln("For a full list, try passing --user=[username]."); } diff --git a/src/Command/AngularHtmlShowCommand.php b/src/Command/AngularHtmlShowCommand.php index 9114b5ae..d3bd80d8 100644 --- a/src/Command/AngularHtmlShowCommand.php +++ b/src/Command/AngularHtmlShowCommand.php @@ -38,7 +38,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); if (!$input->getOption('user')) { $output->getErrorOutput()->writeln("For a full list, try passing --user=[username]."); } diff --git a/src/Command/AngularModuleListCommand.php b/src/Command/AngularModuleListCommand.php index 925018d4..56781bce 100644 --- a/src/Command/AngularModuleListCommand.php +++ b/src/Command/AngularModuleListCommand.php @@ -37,7 +37,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); if (!$input->getOption('user')) { $output->getErrorOutput()->writeln("For a full list, try passing --user=[username]."); } diff --git a/src/Command/Api4Command.php b/src/Command/Api4Command.php index 4a3668ba..a5f045b8 100644 --- a/src/Command/Api4Command.php +++ b/src/Command/Api4Command.php @@ -128,8 +128,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $I = ''; $_I = ''; - $this->boot($input, $output); - if (!function_exists('civicrm_api4')) { throw new \RuntimeException("Please enable APIv4 before running APIv4 commands."); } diff --git a/src/Command/ApiBatchCommand.php b/src/Command/ApiBatchCommand.php index c8a4c3e7..49bd8786 100644 --- a/src/Command/ApiBatchCommand.php +++ b/src/Command/ApiBatchCommand.php @@ -60,7 +60,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int // Other formats may not work with the fgets() loop. throw new \Exception("api:batch only supports JSON dialog"); } - $this->boot($input, $output); $addDefault = function($v) { $this->defaults = \CRM_Utils_Array::crmArrayMerge($v, $this->defaults); diff --git a/src/Command/ApiCommand.php b/src/Command/ApiCommand.php index 4ceb348b..6a73dbcd 100644 --- a/src/Command/ApiCommand.php +++ b/src/Command/ApiCommand.php @@ -53,8 +53,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $I = ''; $_I = ''; - $this->boot($input, $output); - list($entity, $action) = explode('.', $input->getArgument('Entity.action')); $params = $this->parseParams($input); diff --git a/src/Command/BootCommand.php b/src/Command/BootCommand.php index beac59de..c0350911 100644 --- a/src/Command/BootCommand.php +++ b/src/Command/BootCommand.php @@ -13,8 +13,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - switch ($input->getOption('level')) { case 'classloader': $code = sprintf('require_once %s . "/CRM/Core/ClassLoader.php";', var_export(rtrim($GLOBALS["civicrm_root"], '/'), 1)) diff --git a/src/Command/CliCommand.php b/src/Command/CliCommand.php index 789c2d5c..eb3fbd7c 100644 --- a/src/Command/CliCommand.php +++ b/src/Command/CliCommand.php @@ -18,8 +18,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - $cv = new Application(); $sh = new \Psy\Shell(); $sh->addCommands($cv->createCommands()); diff --git a/src/Command/DebugContainerCommand.php b/src/Command/DebugContainerCommand.php index 4f9a63ef..6824751c 100644 --- a/src/Command/DebugContainerCommand.php +++ b/src/Command/DebugContainerCommand.php @@ -33,11 +33,13 @@ protected function configure() { '); } - protected function execute(InputInterface $input, OutputInterface $output): int { + protected function initialize(InputInterface $input, OutputInterface $output) { define('CIVICRM_CONTAINER_CACHE', 'never'); $output->getErrorOutput()->writeln('The debug command ignores the container cache.'); - $this->boot($input, $output); + parent::initialize($input, $output); + } + protected function execute(InputInterface $input, OutputInterface $output): int { $c = $this->getInspectableContainer($input); $filterPat = $input->getArgument('name'); diff --git a/src/Command/DebugDispatcherCommand.php b/src/Command/DebugDispatcherCommand.php index c094c672..a7a2500d 100644 --- a/src/Command/DebugDispatcherCommand.php +++ b/src/Command/DebugDispatcherCommand.php @@ -27,11 +27,13 @@ protected function configure() { '); } - protected function execute(InputInterface $input, OutputInterface $output): int { + protected function initialize(InputInterface $input, OutputInterface $output) { define('CIVICRM_CONTAINER_CACHE', 'never'); $output->getErrorOutput()->writeln('The debug command ignores the container cache.'); - $this->boot($input, $output); + parent::initialize($input, $output); + } + protected function execute(InputInterface $input, OutputInterface $output): int { $container = \Civi::container(); /* diff --git a/src/Command/EditCommand.php b/src/Command/EditCommand.php index 7b9a3274..d1daa858 100644 --- a/src/Command/EditCommand.php +++ b/src/Command/EditCommand.php @@ -43,8 +43,6 @@ public function __construct($name = NULL) { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - $config = Config::read(); $oldSiteData = empty($config['sites'][CIVICRM_SETTINGS_PATH]) ? array() : $config['sites'][CIVICRM_SETTINGS_PATH]; $oldJson = Encoder::encode($oldSiteData, 'json-pretty'); diff --git a/src/Command/EvalCommand.php b/src/Command/EvalCommand.php index 4cb8e4d6..2c5b960a 100644 --- a/src/Command/EvalCommand.php +++ b/src/Command/EvalCommand.php @@ -38,8 +38,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - if ($input->getOption('out') === 'auto') { $hasReturn = preg_match('/^\s*return[ \t\r\n]/', $input->getArgument('code')) || preg_match('/[;\{]\s*return[ \t\r\n]/', $input->getArgument('code')); diff --git a/src/Command/ExtensionDisableCommand.php b/src/Command/ExtensionDisableCommand.php index b5ad7b71..fe3c2975 100644 --- a/src/Command/ExtensionDisableCommand.php +++ b/src/Command/ExtensionDisableCommand.php @@ -38,7 +38,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); [$foundKeys, $missingKeys] = $this->parseKeys($input, $output); // Uninstall what's recognized or what looks like an ext key. diff --git a/src/Command/ExtensionDownloadCommand.php b/src/Command/ExtensionDownloadCommand.php index 1921db30..2cef9853 100644 --- a/src/Command/ExtensionDownloadCommand.php +++ b/src/Command/ExtensionDownloadCommand.php @@ -65,18 +65,15 @@ protected function initialize(InputInterface $input, OutputInterface $output) { $input->setOption('level', 'none'); $input->setOption('no-install', TRUE); } - parent::initialize($input, $output); - } - - protected function execute(InputInterface $input, OutputInterface $output): int { - $fs = new Filesystem(); - if ($extRepoUrl = $this->parseRepoUrl($input)) { global $civicrm_setting; $civicrm_setting['Extension Preferences']['ext_repo_url'] = $extRepoUrl; } + parent::initialize($input, $output); + } - $this->boot($input, $output); + protected function execute(InputInterface $input, OutputInterface $output): int { + $fs = new Filesystem(); if ($input->getOption('to') && !$fs->isAbsolutePath($input->getOption('to'))) { throw new \RuntimeException("The --to argument requires an absolute path."); diff --git a/src/Command/ExtensionEnableCommand.php b/src/Command/ExtensionEnableCommand.php index 26f57957..2ba86313 100644 --- a/src/Command/ExtensionEnableCommand.php +++ b/src/Command/ExtensionEnableCommand.php @@ -41,8 +41,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - // Refresh extensions if (a) ---refresh enabled or (b) there's a cache-miss. $refresh = $input->getOption('refresh') ? 'yes' : 'auto'; // $refresh = OptionalOption::parse(array('--refresh', '-r'), 'auto', 'yes'); diff --git a/src/Command/ExtensionListCommand.php b/src/Command/ExtensionListCommand.php index 78dcc6b5..218527c9 100644 --- a/src/Command/ExtensionListCommand.php +++ b/src/Command/ExtensionListCommand.php @@ -61,6 +61,11 @@ protected function configure() { } protected function initialize(InputInterface $input, OutputInterface $output) { + if ($extRepoUrl = $this->parseRepoUrl($input)) { + global $civicrm_setting; + $civicrm_setting['Extension Preferences']['ext_repo_url'] = $extRepoUrl; + } + parent::initialize($input, $output); // We apply different defaults for the 'columns' list depending on the output medium. @@ -84,13 +89,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int [$local, $remote] = $this->parseLocalRemote($input); - if ($extRepoUrl = $this->parseRepoUrl($input)) { - global $civicrm_setting; - $civicrm_setting['Extension Preferences']['ext_repo_url'] = $extRepoUrl; - } - - $this->boot($input, $output); - if ($remote) { $output->writeln("Using extension feed \"" . \CRM_Extension_System::singleton()->getBrowser()->getRepositoryUrl() . "\"", $wo); } diff --git a/src/Command/ExtensionUninstallCommand.php b/src/Command/ExtensionUninstallCommand.php index a90dc948..74e77852 100644 --- a/src/Command/ExtensionUninstallCommand.php +++ b/src/Command/ExtensionUninstallCommand.php @@ -38,7 +38,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); [$foundKeys, $missingKeys] = $this->parseKeys($input, $output); // Uninstall what's recognized or what looks like an ext key. diff --git a/src/Command/ExtensionUpgradeDbCommand.php b/src/Command/ExtensionUpgradeDbCommand.php index 07539111..13e1b6cb 100644 --- a/src/Command/ExtensionUpgradeDbCommand.php +++ b/src/Command/ExtensionUpgradeDbCommand.php @@ -34,10 +34,12 @@ protected function configure() { '); } - protected function execute(InputInterface $input, OutputInterface $output): int { + protected function initialize(InputInterface $input, OutputInterface $output) { $output->writeln("WARNING: \"ext:upgrade-db\" is deprecated. Use the main \"updb\" command instead."); - $this->boot($input, $output); + parent::initialize($input, $output); + } + protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln("Applying database upgrades from extensions"); $result = VerboseApi::callApi3Success('Extension', 'upgrade', array()); if (!empty($result['is_error'])) { diff --git a/src/Command/FillCommand.php b/src/Command/FillCommand.php index cc62263a..91eb22de 100644 --- a/src/Command/FillCommand.php +++ b/src/Command/FillCommand.php @@ -55,7 +55,6 @@ public function __construct($name = NULL) { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); if (!$input->getOption('file')) { $reader = new SiteConfigReader(CIVICRM_SETTINGS_PATH); $liveData = $reader->compile(array('buildkit', 'home', 'active')); diff --git a/src/Command/FlushCommand.php b/src/Command/FlushCommand.php index f0aab4f8..6b3cab44 100644 --- a/src/Command/FlushCommand.php +++ b/src/Command/FlushCommand.php @@ -19,10 +19,15 @@ protected function configure() { '); } - protected function execute(InputInterface $input, OutputInterface $output): int { + protected function initialize(InputInterface $input, OutputInterface $output) { // The main reason we have this as separate command -- so we can ignore // stale class-references that might be retained by the container cache. define('CIVICRM_CONTAINER_CACHE', 'never'); + + parent::initialize($input, $output); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { $this->boot($input, $output); $params = array(); diff --git a/src/Command/HttpCommand.php b/src/Command/HttpCommand.php index af44f2e5..c2ec6a78 100644 --- a/src/Command/HttpCommand.php +++ b/src/Command/HttpCommand.php @@ -46,8 +46,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - $method = $input->getOption('request'); $data = $this->parseRequestData($input); $headers = $this->parseRequestHeaders($input); diff --git a/src/Command/PathCommand.php b/src/Command/PathCommand.php index 183e16d3..dcdfe139 100644 --- a/src/Command/PathCommand.php +++ b/src/Command/PathCommand.php @@ -58,8 +58,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - if (!$input->getOption('ext') && !$input->getOption('config') && !$input->getOption('dynamic')) { $output->getErrorOutput()->writeln("No paths specified. Must use -x, -c, or -d. (See also: cv path -h)"); return 1; diff --git a/src/Command/PipeCommand.php b/src/Command/PipeCommand.php index 8668d683..7e2bb51d 100644 --- a/src/Command/PipeCommand.php +++ b/src/Command/PipeCommand.php @@ -46,7 +46,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); if (!is_callable(['Civi', 'pipe'])) { fwrite(STDERR, "This version of CiviCRM does not include Civi::pipe() support.\n"); return 1; diff --git a/src/Command/ScriptCommand.php b/src/Command/ScriptCommand.php index 21943788..5f8b71ca 100644 --- a/src/Command/ScriptCommand.php +++ b/src/Command/ScriptCommand.php @@ -17,6 +17,10 @@ protected function configure() { ->addArgument('scriptArguments', InputArgument::IS_ARRAY, 'Optional arguments to pass to the script as $argv'); } + public function getBootOptions(): array { + return parent::getBootOptions() + ['auto' => FALSE]; + } + protected function execute(InputInterface $input, OutputInterface $output): int { $fs = new Filesystem(); $origScript = $fs->toAbsolutePath($input->getArgument('script')); diff --git a/src/Command/SettingGetCommand.php b/src/Command/SettingGetCommand.php index a2cd4e03..9af13a4a 100644 --- a/src/Command/SettingGetCommand.php +++ b/src/Command/SettingGetCommand.php @@ -69,8 +69,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - $filter = $this->createSettingFilter($input->getArgument('name')); $result = []; diff --git a/src/Command/SettingRevertCommand.php b/src/Command/SettingRevertCommand.php index 3a6cdd86..c1ba4766 100644 --- a/src/Command/SettingRevertCommand.php +++ b/src/Command/SettingRevertCommand.php @@ -60,7 +60,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); $errorOutput = is_callable([$output, 'getErrorOutput']) ? $output->getErrorOutput() : $output; $filter = $this->createSettingFilter($input->getArgument('name')); diff --git a/src/Command/SettingSetCommand.php b/src/Command/SettingSetCommand.php index f3620019..14f15f5f 100644 --- a/src/Command/SettingSetCommand.php +++ b/src/Command/SettingSetCommand.php @@ -88,7 +88,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $I = ''; $_I = ''; - $this->boot($input, $output); $errorOutput = is_callable([$output, 'getErrorOutput']) ? $output->getErrorOutput() : $output; $result = []; diff --git a/src/Command/ShowCommand.php b/src/Command/ShowCommand.php index 2a6ce619..f33b3401 100644 --- a/src/Command/ShowCommand.php +++ b/src/Command/ShowCommand.php @@ -18,7 +18,6 @@ protected function configure() { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); $reader = new SiteConfigReader(CIVICRM_SETTINGS_PATH); $data = $reader->compile(array('buildkit', 'home', 'active')); $this->sendResult($input, $output, $data); diff --git a/src/Command/SqlCliCommand.php b/src/Command/SqlCliCommand.php index 9bd993e4..65b29933 100644 --- a/src/Command/SqlCliCommand.php +++ b/src/Command/SqlCliCommand.php @@ -44,8 +44,6 @@ protected function initialize(InputInterface $input, OutputInterface $output) { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->boot($input, $output); - $datasource = new Datasource(); $datasource->loadFromCiviDSN($this->pickDsn($input->getOption('target'))); diff --git a/src/Command/UpgradeDbCommand.php b/src/Command/UpgradeDbCommand.php index 7b5386d3..37c64899 100644 --- a/src/Command/UpgradeDbCommand.php +++ b/src/Command/UpgradeDbCommand.php @@ -49,15 +49,13 @@ protected function configure() { protected function initialize(InputInterface $input, OutputInterface $output) { $this->input = $input; $this->output = $output; - parent::initialize($input, $output); - } - - protected function execute(InputInterface $input, OutputInterface $output): int { if (!defined('CIVICRM_UPGRADE_ACTIVE')) { define('CIVICRM_UPGRADE_ACTIVE', 1); } - $this->boot($input, $output); + parent::initialize($input, $output); + } + protected function execute(InputInterface $input, OutputInterface $output): int { if (!ini_get('safe_mode')) { set_time_limit(0); } diff --git a/src/Command/UpgradeGetCommand.php b/src/Command/UpgradeGetCommand.php index a8f87d10..daae009d 100644 --- a/src/Command/UpgradeGetCommand.php +++ b/src/Command/UpgradeGetCommand.php @@ -39,6 +39,10 @@ protected function configure() { '); } + public function getBootOptions(): array { + return parent::getBootOptions() + ['auto' => FALSE]; + } + protected function execute(InputInterface $input, OutputInterface $output): int { $result = array(); $exitCode = 0; diff --git a/src/Command/UrlCommand.php b/src/Command/UrlCommand.php index 2ce822a0..c8dbbb9c 100644 --- a/src/Command/UrlCommand.php +++ b/src/Command/UrlCommand.php @@ -69,20 +69,17 @@ protected function configure() { } protected function initialize(InputInterface $input, OutputInterface $output) { - parent::initialize($input, $output); if ($input->getFirstArgument() === 'open') { $input->setOption('open', TRUE); } - } - - protected function execute(InputInterface $input, OutputInterface $output): int { if (in_array($input->getOption('out'), Encoder::getTabularFormats()) && !in_array($input->getOption('out'), Encoder::getFormats())) { $input->setOption('tabular', TRUE); } + parent::initialize($input, $output); + } - $this->boot($input, $output); - + protected function execute(InputInterface $input, OutputInterface $output): int { $rows = $this->createUrls($input, $output); if ($input->getOption('open')) { From 16999f7787a92ad3a6c71a7449a73dc4dcff1eb7 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 23 Sep 2024 23:23:19 -0700 Subject: [PATCH 09/16] lib/README.md --- lib/README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/README.md b/lib/README.md index 5f79d6ce..c45a3305 100644 --- a/lib/README.md +++ b/lib/README.md @@ -78,11 +78,13 @@ For more info about `$options`, see the docblocks. ## Experimental API -Other classes are included, but their contracts are subject to change. - -A particularly interesting one is `BootTrait`. This requires `symfony/console`, and it is used by most `cv` subcommands -to achieve common behaviors: - -1. `BootTrait` defines certain CLI options (`--level`, `--user`, `--hostname`, etc). -2. `BootTrait` automatically decides between `Bootstrap.php` and `CmsBootstrap.php`. -3. `BootTrait` passes CLI options through to `Bootstrap.php` or `CmsBootstrap.php`. +Other classes are included, but their contracts are subject to change. These +include higher-level helpers for building Symfony Console apps that incorporate +Civi bootstrap behaviors. + +* `BootTrait` has previously suggested as an experimentally available API + (circa v0.3.44). It changed significantly (circa v0.3.56), where + `configureBootOptions()` was replaced by `$bootOptions`, `mergeDefaultBootDefinition()`, + and `mergeBootDefinition()`. +* As an alternative, consider the classes `BaseApplication` and `BaseCommand` if you aim + to build a tool using Symfony Console and Cv Lib. From 45247375faeab449470b8f93bd4313a5f037e74c Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 00:58:36 -0700 Subject: [PATCH 10/16] Move BaseCommand from cv-app to cv-lib --- {src => lib/src}/Command/BaseCommand.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src => lib/src}/Command/BaseCommand.php (100%) diff --git a/src/Command/BaseCommand.php b/lib/src/Command/BaseCommand.php similarity index 100% rename from src/Command/BaseCommand.php rename to lib/src/Command/BaseCommand.php From c100f6ffc6da72884c0c15a8c7f200facaf782e4 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 09:14:01 -0700 Subject: [PATCH 11/16] (REF) Demonstrate $bootOptions['auto'] more clearly --- lib/src/Command/BaseCommand.php | 1 + src/Command/ScriptCommand.php | 2 +- src/Command/UpgradeGetCommand.php | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/Command/BaseCommand.php b/lib/src/Command/BaseCommand.php index 7f352a07..e60fd935 100644 --- a/lib/src/Command/BaseCommand.php +++ b/lib/src/Command/BaseCommand.php @@ -14,6 +14,7 @@ class BaseCommand extends Command { public function getBootOptions(): array { return [ + 'auto' => TRUE, 'default' => 'full|cms-full', 'allow' => ['full|cms-full', 'full', 'cms-full', 'settings', 'classloader', 'cms-only', 'none'], ]; diff --git a/src/Command/ScriptCommand.php b/src/Command/ScriptCommand.php index 5f8b71ca..41364e0f 100644 --- a/src/Command/ScriptCommand.php +++ b/src/Command/ScriptCommand.php @@ -18,7 +18,7 @@ protected function configure() { } public function getBootOptions(): array { - return parent::getBootOptions() + ['auto' => FALSE]; + return ['auto' => FALSE] + parent::getBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/UpgradeGetCommand.php b/src/Command/UpgradeGetCommand.php index daae009d..6d2da3bc 100644 --- a/src/Command/UpgradeGetCommand.php +++ b/src/Command/UpgradeGetCommand.php @@ -40,7 +40,7 @@ protected function configure() { } public function getBootOptions(): array { - return parent::getBootOptions() + ['auto' => FALSE]; + return ['auto' => FALSE] + parent::getBootOptions(); } protected function execute(InputInterface $input, OutputInterface $output): int { From e1e3d45b09aaeb7347d39430fc80900585285cf8 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 09:15:25 -0700 Subject: [PATCH 12/16] (NFC) BaseCommand --- lib/src/Command/BaseCommand.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/src/Command/BaseCommand.php b/lib/src/Command/BaseCommand.php index e60fd935..d615a0e4 100644 --- a/lib/src/Command/BaseCommand.php +++ b/lib/src/Command/BaseCommand.php @@ -7,6 +7,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +/** + * Cv's `BaseCommand` is a Symfony `Command` with support for bootstrapping CiviCRM/CMS. + * + * - From end-user POV, the command accepts options like --user, --level, --hostname. + * - From dev POV, the command allows you to implement `execute()` method without needing to + * explicitly boot Civi. + * - From dev POV, you may fine-tune command by changing the $bootOptions / getBootOptions(). + */ class BaseCommand extends Command { use OptionCallbackTrait; From 4cbdf55d2e8eb4dc1f9174c58556354c61ef20fc Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 09:28:37 -0700 Subject: [PATCH 13/16] Move getBootOptions (etc) from BaseApplication to BootTrait --- lib/src/BaseApplication.php | 2 +- lib/src/Command/BaseCommand.php | 22 +--------- lib/src/Util/BootTrait.php | 72 ++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/lib/src/BaseApplication.php b/lib/src/BaseApplication.php index d93d0b5e..dcc881e0 100644 --- a/lib/src/BaseApplication.php +++ b/lib/src/BaseApplication.php @@ -72,7 +72,7 @@ protected function getDefaultInputDefinition() { $c = new class() { use BootTrait; }; - $c->configureDefinition($definition); + $c->mergeDefaultBootDefinition($definition); return $definition; } diff --git a/lib/src/Command/BaseCommand.php b/lib/src/Command/BaseCommand.php index d615a0e4..e896cb81 100644 --- a/lib/src/Command/BaseCommand.php +++ b/lib/src/Command/BaseCommand.php @@ -20,18 +20,9 @@ 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()); } /** @@ -39,16 +30,7 @@ public function mergeApplicationDefinition($mergeArgs = TRUE) { * @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); } diff --git a/lib/src/Util/BootTrait.php b/lib/src/Util/BootTrait.php index 70360f67..300ec9fc 100644 --- a/lib/src/Util/BootTrait.php +++ b/lib/src/Util/BootTrait.php @@ -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'); @@ -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; + } + } From 44d7c5b5078709b2f910edd627c9815b5d0f0d37 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 11:20:51 -0700 Subject: [PATCH 14/16] BaseCommand - Suggest fluent style for plugin files --- doc/plugins.md | 17 ++--- lib/src/Util/BootTrait.php | 2 +- tests/Plugin/FluentHelloPluginTest.php | 39 +++++++++++ tests/Plugin/FluentHelloPluginTest/hello.php | 68 ++++++++++++++++++++ 4 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 tests/Plugin/FluentHelloPluginTest.php create mode 100644 tests/Plugin/FluentHelloPluginTest/hello.php diff --git a/doc/plugins.md b/doc/plugins.md index 0235d803..144afd5d 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -8,6 +8,7 @@ Cv plugins are PHP files which register event listeners. // FILE: /etc/cv/plugin/hello-command.php use Civi\Cv\Cv; use CvDeps\Symfony\Component\Console\Input\InputInterface; +use CvDeps\Symfony\Component\Console\Input\InputArgument; use CvDeps\Symfony\Component\Console\Output\OutputInterface; use CvDeps\Symfony\Component\Console\Command\Command; @@ -16,15 +17,15 @@ if (empty($CV_PLUGIN['protocol']) || $CV_PLUGIN['protocol'] > 1) { } Cv::dispatcher()->addListener('cv.app.commands', function($e) { - $e['commands'][] = new class extends Command { - protected function configure() { - $this->setName('hello')->setDescription('Say a greeting'); - } - protected function execute(InputInterface $input, OutputInterface $output): int { - $output->writeln('Hello there!'); + + $e['commands'][] = (new \Civi\Cv\Command\BaseCommand('hello')) + ->setDescription('Say a greeting') + ->addArgument('name', InputArgument::REQUIRED, 'Name of the person to greet') + ->setCode(function($input, $output) { + $output->writeln('Hello, ' . $input->getArgument('name')); return 0; - } - }; + }); + }); ``` diff --git a/lib/src/Util/BootTrait.php b/lib/src/Util/BootTrait.php index 300ec9fc..2db48498 100644 --- a/lib/src/Util/BootTrait.php +++ b/lib/src/Util/BootTrait.php @@ -372,7 +372,7 @@ public function getBootOptions(): array { * @return $this */ public function setBootOptions(array $bootOptions) { - $this->bootOptions = $bootOptions; + $this->bootOptions = array_merge($this->bootOptions, $bootOptions); return $this; } diff --git a/tests/Plugin/FluentHelloPluginTest.php b/tests/Plugin/FluentHelloPluginTest.php new file mode 100644 index 00000000..6bc843d6 --- /dev/null +++ b/tests/Plugin/FluentHelloPluginTest.php @@ -0,0 +1,39 @@ +setEnv(['CV_PLUGIN_PATH' => preg_replace(';\.php$;', '', __FILE__)]); + return $process; + } + + public function testRun() { + $output = $this->cvOk('hello:normal'); + $this->assertMatchesRegularExpression('/Hey-yo world via parameter.*Hey-yo world via StyleInterface/s', $output); + } + + public function testRunWithName() { + $output = $this->cvOk('hello:normal Alice'); + $this->assertMatchesRegularExpression('/Hey-yo Alice via parameter.*Hey-yo Alice via StyleInterface/s', $output); + } + + public function testRun_noboot() { + $output = $this->cvOk('hello:noboot'); + $this->assertMatchesRegularExpression('/Hey-yo world via parameter.*Hey-yo world via StyleInterface/s', $output); + } + + public function testRunWithName_noboot() { + $output = $this->cvOk('hello:noboot Bob'); + $this->assertMatchesRegularExpression('/Hey-yo Bob via parameter.*Hey-yo Bob via StyleInterface/s', $output); + } + +} diff --git a/tests/Plugin/FluentHelloPluginTest/hello.php b/tests/Plugin/FluentHelloPluginTest/hello.php new file mode 100644 index 00000000..8c5a36b7 --- /dev/null +++ b/tests/Plugin/FluentHelloPluginTest/hello.php @@ -0,0 +1,68 @@ + 1) { + die("Expect CV_PLUGIN API v1"); +} + +if (!preg_match(';^[\w_-]+$;', $CV_PLUGIN['appName'])) { + throw new \RuntimeException("Invalid CV_PLUGIN[appName]" . json_encode($CV_PLUGIN['appName'])); +} + +if (!preg_match(';^([0-9x\.]+(-[\w-]+)?|UNKNOWN)$;', $CV_PLUGIN['appVersion'])) { + throw new \RuntimeException("Invalid CV_PLUGIN[appVersion]: " . json_encode($CV_PLUGIN['appVersion'])); +} + +if ($CV_PLUGIN['name'] !== 'hello') { + throw new \RuntimeException("Invalid CV_PLUGIN[name]"); +} +if (realpath($CV_PLUGIN['file']) !== realpath(__FILE__)) { + throw new \RuntimeException("Invalid CV_PLUGIN[file]"); +} + +Cv::dispatcher()->addListener('*.app.boot', function ($e) { + Cv::io()->writeln("Hey-yo during initial bootstrap!"); +}); + +Cv::dispatcher()->addListener('cv.app.commands', function ($e) { + + $e['commands'][] = (new BaseCommand('hello:normal')) + ->setDescription('Say a greeting') + ->addArgument('name') + ->setCode(function($input, $output) { + // ASSERT: With setCode(), it's OK to use un-hinted inputs. + if ($input->getArgument('name') !== Cv::input()->getArgument('name')) { + throw new \RuntimeException("Argument \"name\" is inconsistent!"); + } + if (!Civi\Core\Container::isContainerBooted()) { + throw new \LogicException("Container should have been booted by BaseCommand!"); + } + $name = $input->getArgument('name') ?: 'world'; + $output->writeln("Hey-yo $name via parameter!"); + Cv::io()->writeln("Hey-yo $name via StyleInterface!"); + return 0; + }); + + $e['commands'][] = (new BaseCommand('hello:noboot')) + ->setDescription('Say a greeting') + ->addArgument('name') + ->setBootOptions(['auto' => FALSE]) + ->setCode(function(InputInterface $input, OutputInterface $output) { + // ASSERT: With setCode(), it's OK to use hinted inputs. + if ($input->getArgument('name') !== Cv::input()->getArgument('name')) { + throw new \RuntimeException("Argument \"name\" is inconsistent!"); + } + if (class_exists('Civi\Core\Container')) { + throw new \LogicException("Container should not have been booted by BaseCommand!"); + } + $name = $input->getArgument('name') ?: 'world'; + $output->writeln("Hey-yo $name via parameter!"); + Cv::io()->writeln("Hey-yo $name via StyleInterface!"); + return 0; + }); + +}); From bbccfc4bd601507ef0c66e7caecd7f29f0247f8b Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 11:31:36 -0700 Subject: [PATCH 15/16] (REF) Convert BaseExtensionCommand to BaseCommand+ExtensionTrait --- src/Command/ExtensionDisableCommand.php | 5 ++++- src/Command/ExtensionDownloadCommand.php | 7 +++++-- src/Command/ExtensionEnableCommand.php | 5 ++++- src/Command/ExtensionListCommand.php | 6 ++++-- src/Command/ExtensionUninstallCommand.php | 5 ++++- src/Command/ExtensionUpgradeDbCommand.php | 5 ++++- src/Command/HttpCommand.php | 4 +++- src/Command/PathCommand.php | 4 +++- src/Command/UrlCommand.php | 4 +++- .../BaseExtensionCommand.php => Util/ExtensionTrait.php} | 5 +++-- tests/Command/BaseExtensionCommandTest.php | 5 ++++- 11 files changed, 41 insertions(+), 14 deletions(-) rename src/{Command/BaseExtensionCommand.php => Util/ExtensionTrait.php} (96%) diff --git a/src/Command/ExtensionDisableCommand.php b/src/Command/ExtensionDisableCommand.php index fe3c2975..0e72889b 100644 --- a/src/Command/ExtensionDisableCommand.php +++ b/src/Command/ExtensionDisableCommand.php @@ -1,12 +1,15 @@ configureRepoOptions(); } protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/src/Command/ExtensionEnableCommand.php b/src/Command/ExtensionEnableCommand.php index 2ba86313..1cef2a6b 100644 --- a/src/Command/ExtensionEnableCommand.php +++ b/src/Command/ExtensionEnableCommand.php @@ -1,13 +1,16 @@ configureRepoOptions(); } protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/src/Command/ExtensionUninstallCommand.php b/src/Command/ExtensionUninstallCommand.php index 74e77852..b8aef554 100644 --- a/src/Command/ExtensionUninstallCommand.php +++ b/src/Command/ExtensionUninstallCommand.php @@ -1,12 +1,15 @@ $keys, 1=>$errors). */ diff --git a/tests/Command/BaseExtensionCommandTest.php b/tests/Command/BaseExtensionCommandTest.php index 83bc2bbc..dc28ff0e 100644 --- a/tests/Command/BaseExtensionCommandTest.php +++ b/tests/Command/BaseExtensionCommandTest.php @@ -1,6 +1,7 @@ configureRepoOptions(); $input = new ArgvInput($inputArgv, $c->getDefinition()); From 149bb4a2d45aa5a3974bddf0b62de166df8632df Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 24 Sep 2024 11:39:58 -0700 Subject: [PATCH 16/16] (REF) Rename BaseCommand to CvCommand It can be used in either inherited style or fluent style. And this symbol has not yet been published via cv-lib --- doc/plugins.md | 3 ++- lib/README.md | 2 +- lib/src/Command/{BaseCommand.php => CvCommand.php} | 4 ++-- src/Command/AngularHtmlListCommand.php | 2 +- src/Command/AngularHtmlShowCommand.php | 2 +- src/Command/AngularModuleListCommand.php | 2 +- src/Command/Api4Command.php | 2 +- src/Command/ApiBatchCommand.php | 2 +- src/Command/ApiCommand.php | 2 +- src/Command/BootCommand.php | 2 +- src/Command/CliCommand.php | 2 +- src/Command/CoreCheckReqCommand.php | 2 +- src/Command/CoreInstallCommand.php | 2 +- src/Command/CoreUninstallCommand.php | 2 +- src/Command/DebugContainerCommand.php | 2 +- src/Command/DebugDispatcherCommand.php | 2 +- src/Command/EditCommand.php | 2 +- src/Command/EvalCommand.php | 2 +- src/Command/ExtensionDisableCommand.php | 2 +- src/Command/ExtensionDownloadCommand.php | 2 +- src/Command/ExtensionEnableCommand.php | 2 +- src/Command/ExtensionListCommand.php | 2 +- src/Command/ExtensionUninstallCommand.php | 2 +- src/Command/ExtensionUpgradeDbCommand.php | 2 +- src/Command/FillCommand.php | 2 +- src/Command/FlushCommand.php | 2 +- src/Command/HttpCommand.php | 2 +- src/Command/PathCommand.php | 2 +- src/Command/PipeCommand.php | 2 +- src/Command/ScriptCommand.php | 2 +- src/Command/SettingGetCommand.php | 2 +- src/Command/SettingRevertCommand.php | 2 +- src/Command/SettingSetCommand.php | 2 +- src/Command/ShowCommand.php | 2 +- src/Command/SqlCliCommand.php | 2 +- src/Command/UpgradeCommand.php | 2 +- src/Command/UpgradeDbCommand.php | 2 +- src/Command/UpgradeDlCommand.php | 2 +- src/Command/UpgradeGetCommand.php | 2 +- src/Command/UpgradeReportCommand.php | 2 +- src/Command/UrlCommand.php | 2 +- tests/Command/BaseExtensionCommandTest.php | 2 +- tests/Plugin/FluentHelloPluginTest/hello.php | 10 +++++----- 43 files changed, 49 insertions(+), 48 deletions(-) rename lib/src/Command/{BaseCommand.php => CvCommand.php} (90%) diff --git a/doc/plugins.md b/doc/plugins.md index 144afd5d..541d091d 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -7,6 +7,7 @@ Cv plugins are PHP files which register event listeners. ```php // FILE: /etc/cv/plugin/hello-command.php use Civi\Cv\Cv; +use Civi\Cv\Command\CvCommand; use CvDeps\Symfony\Component\Console\Input\InputInterface; use CvDeps\Symfony\Component\Console\Input\InputArgument; use CvDeps\Symfony\Component\Console\Output\OutputInterface; @@ -18,7 +19,7 @@ if (empty($CV_PLUGIN['protocol']) || $CV_PLUGIN['protocol'] > 1) { Cv::dispatcher()->addListener('cv.app.commands', function($e) { - $e['commands'][] = (new \Civi\Cv\Command\BaseCommand('hello')) + $e['commands'][] = (new CvCommand('hello')) ->setDescription('Say a greeting') ->addArgument('name', InputArgument::REQUIRED, 'Name of the person to greet') ->setCode(function($input, $output) { diff --git a/lib/README.md b/lib/README.md index c45a3305..3ce8352f 100644 --- a/lib/README.md +++ b/lib/README.md @@ -86,5 +86,5 @@ Civi bootstrap behaviors. (circa v0.3.44). It changed significantly (circa v0.3.56), where `configureBootOptions()` was replaced by `$bootOptions`, `mergeDefaultBootDefinition()`, and `mergeBootDefinition()`. -* As an alternative, consider the classes `BaseApplication` and `BaseCommand` if you aim +* As an alternative, consider the classes `BaseApplication` and `CvCommand` if you aim to build a tool using Symfony Console and Cv Lib. diff --git a/lib/src/Command/BaseCommand.php b/lib/src/Command/CvCommand.php similarity index 90% rename from lib/src/Command/BaseCommand.php rename to lib/src/Command/CvCommand.php index e896cb81..d6bc5616 100644 --- a/lib/src/Command/BaseCommand.php +++ b/lib/src/Command/CvCommand.php @@ -8,14 +8,14 @@ use Symfony\Component\Console\Output\OutputInterface; /** - * Cv's `BaseCommand` is a Symfony `Command` with support for bootstrapping CiviCRM/CMS. + * `CvCommand` is a Symfony `Command` with support for bootstrapping CiviCRM/CMS. * * - From end-user POV, the command accepts options like --user, --level, --hostname. * - From dev POV, the command allows you to implement `execute()` method without needing to * explicitly boot Civi. * - From dev POV, you may fine-tune command by changing the $bootOptions / getBootOptions(). */ -class BaseCommand extends Command { +class CvCommand extends Command { use OptionCallbackTrait; use BootTrait; diff --git a/src/Command/AngularHtmlListCommand.php b/src/Command/AngularHtmlListCommand.php index 84657424..9ced3f51 100644 --- a/src/Command/AngularHtmlListCommand.php +++ b/src/Command/AngularHtmlListCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class AngularHtmlListCommand extends BaseCommand { +class AngularHtmlListCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/AngularHtmlShowCommand.php b/src/Command/AngularHtmlShowCommand.php index d3bd80d8..fed17693 100644 --- a/src/Command/AngularHtmlShowCommand.php +++ b/src/Command/AngularHtmlShowCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class AngularHtmlShowCommand extends BaseCommand { +class AngularHtmlShowCommand extends CvCommand { /** * @param string|null $name diff --git a/src/Command/AngularModuleListCommand.php b/src/Command/AngularModuleListCommand.php index 56781bce..73dbe08c 100644 --- a/src/Command/AngularModuleListCommand.php +++ b/src/Command/AngularModuleListCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class AngularModuleListCommand extends BaseCommand { +class AngularModuleListCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/Api4Command.php b/src/Command/Api4Command.php index a5f045b8..40e0b37c 100644 --- a/src/Command/Api4Command.php +++ b/src/Command/Api4Command.php @@ -9,7 +9,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class Api4Command extends BaseCommand { +class Api4Command extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/ApiBatchCommand.php b/src/Command/ApiBatchCommand.php index 49bd8786..8c0bdc71 100644 --- a/src/Command/ApiBatchCommand.php +++ b/src/Command/ApiBatchCommand.php @@ -5,7 +5,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class ApiBatchCommand extends BaseCommand { +class ApiBatchCommand extends CvCommand { /** * @var array diff --git a/src/Command/ApiCommand.php b/src/Command/ApiCommand.php index 6a73dbcd..6713afb2 100644 --- a/src/Command/ApiCommand.php +++ b/src/Command/ApiCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class ApiCommand extends BaseCommand { +class ApiCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/BootCommand.php b/src/Command/BootCommand.php index c0350911..60dc8df1 100644 --- a/src/Command/BootCommand.php +++ b/src/Command/BootCommand.php @@ -4,7 +4,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class BootCommand extends BaseCommand { +class BootCommand extends CvCommand { protected function configure() { $this diff --git a/src/Command/CliCommand.php b/src/Command/CliCommand.php index eb3fbd7c..1d24a05d 100644 --- a/src/Command/CliCommand.php +++ b/src/Command/CliCommand.php @@ -9,7 +9,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class CliCommand extends BaseCommand { +class CliCommand extends CvCommand { protected function configure() { $this diff --git a/src/Command/CoreCheckReqCommand.php b/src/Command/CoreCheckReqCommand.php index 8a1cedc4..033db002 100644 --- a/src/Command/CoreCheckReqCommand.php +++ b/src/Command/CoreCheckReqCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class CoreCheckReqCommand extends BaseCommand { +class CoreCheckReqCommand extends CvCommand { use SetupCommandTrait; use DebugDispatcherTrait; diff --git a/src/Command/CoreInstallCommand.php b/src/Command/CoreInstallCommand.php index 5649932d..96e6bc24 100644 --- a/src/Command/CoreInstallCommand.php +++ b/src/Command/CoreInstallCommand.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; -class CoreInstallCommand extends BaseCommand { +class CoreInstallCommand extends CvCommand { use SetupCommandTrait; use DebugDispatcherTrait; diff --git a/src/Command/CoreUninstallCommand.php b/src/Command/CoreUninstallCommand.php index f8c4dbdd..858b23b7 100644 --- a/src/Command/CoreUninstallCommand.php +++ b/src/Command/CoreUninstallCommand.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; -class CoreUninstallCommand extends BaseCommand { +class CoreUninstallCommand extends CvCommand { use SetupCommandTrait; use DebugDispatcherTrait; diff --git a/src/Command/DebugContainerCommand.php b/src/Command/DebugContainerCommand.php index 6824751c..87673a99 100644 --- a/src/Command/DebugContainerCommand.php +++ b/src/Command/DebugContainerCommand.php @@ -11,7 +11,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; -class DebugContainerCommand extends BaseCommand { +class DebugContainerCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/DebugDispatcherCommand.php b/src/Command/DebugDispatcherCommand.php index a7a2500d..4ca7f609 100644 --- a/src/Command/DebugDispatcherCommand.php +++ b/src/Command/DebugDispatcherCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class DebugDispatcherCommand extends BaseCommand { +class DebugDispatcherCommand extends CvCommand { use DebugDispatcherTrait; diff --git a/src/Command/EditCommand.php b/src/Command/EditCommand.php index d1daa858..9b2375b9 100644 --- a/src/Command/EditCommand.php +++ b/src/Command/EditCommand.php @@ -12,7 +12,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class EditCommand extends BaseCommand { +class EditCommand extends CvCommand { /** * @var \Civi\Cv\Util\CliEditor diff --git a/src/Command/EvalCommand.php b/src/Command/EvalCommand.php index 2c5b960a..81bdb571 100644 --- a/src/Command/EvalCommand.php +++ b/src/Command/EvalCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class EvalCommand extends BaseCommand { +class EvalCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/ExtensionDisableCommand.php b/src/Command/ExtensionDisableCommand.php index 0e72889b..8f17c070 100644 --- a/src/Command/ExtensionDisableCommand.php +++ b/src/Command/ExtensionDisableCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ExtensionDisableCommand extends BaseCommand { +class ExtensionDisableCommand extends CvCommand { use ExtensionTrait; diff --git a/src/Command/ExtensionDownloadCommand.php b/src/Command/ExtensionDownloadCommand.php index 71068e79..105f0591 100644 --- a/src/Command/ExtensionDownloadCommand.php +++ b/src/Command/ExtensionDownloadCommand.php @@ -11,7 +11,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; -class ExtensionDownloadCommand extends BaseCommand { +class ExtensionDownloadCommand extends CvCommand { use ExtensionTrait; diff --git a/src/Command/ExtensionEnableCommand.php b/src/Command/ExtensionEnableCommand.php index 1cef2a6b..73e618e6 100644 --- a/src/Command/ExtensionEnableCommand.php +++ b/src/Command/ExtensionEnableCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class ExtensionEnableCommand extends BaseCommand { +class ExtensionEnableCommand extends CvCommand { use ExtensionTrait; diff --git a/src/Command/ExtensionListCommand.php b/src/Command/ExtensionListCommand.php index 8b65c38b..09e6a63d 100644 --- a/src/Command/ExtensionListCommand.php +++ b/src/Command/ExtensionListCommand.php @@ -12,7 +12,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class ExtensionListCommand extends BaseCommand { +class ExtensionListCommand extends CvCommand { use ExtensionTrait; use StructuredOutputTrait; diff --git a/src/Command/ExtensionUninstallCommand.php b/src/Command/ExtensionUninstallCommand.php index b8aef554..161db433 100644 --- a/src/Command/ExtensionUninstallCommand.php +++ b/src/Command/ExtensionUninstallCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ExtensionUninstallCommand extends BaseCommand { +class ExtensionUninstallCommand extends CvCommand { use ExtensionTrait; diff --git a/src/Command/ExtensionUpgradeDbCommand.php b/src/Command/ExtensionUpgradeDbCommand.php index 26386cdf..5fbbfd81 100644 --- a/src/Command/ExtensionUpgradeDbCommand.php +++ b/src/Command/ExtensionUpgradeDbCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ExtensionUpgradeDbCommand extends BaseCommand { +class ExtensionUpgradeDbCommand extends CvCommand { use ExtensionTrait; diff --git a/src/Command/FillCommand.php b/src/Command/FillCommand.php index 91eb22de..2199d163 100644 --- a/src/Command/FillCommand.php +++ b/src/Command/FillCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class FillCommand extends BaseCommand { +class FillCommand extends CvCommand { protected $fields; diff --git a/src/Command/FlushCommand.php b/src/Command/FlushCommand.php index 6b3cab44..d38e1ed1 100644 --- a/src/Command/FlushCommand.php +++ b/src/Command/FlushCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class FlushCommand extends BaseCommand { +class FlushCommand extends CvCommand { protected function configure() { $this diff --git a/src/Command/HttpCommand.php b/src/Command/HttpCommand.php index c53fc360..e7ccc5a5 100644 --- a/src/Command/HttpCommand.php +++ b/src/Command/HttpCommand.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class HttpCommand extends BaseCommand { +class HttpCommand extends CvCommand { use ExtensionTrait; use StructuredOutputTrait; diff --git a/src/Command/PathCommand.php b/src/Command/PathCommand.php index 773005df..1eef6dd9 100644 --- a/src/Command/PathCommand.php +++ b/src/Command/PathCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class PathCommand extends BaseCommand { +class PathCommand extends CvCommand { use ExtensionTrait; use StructuredOutputTrait; diff --git a/src/Command/PipeCommand.php b/src/Command/PipeCommand.php index 7e2bb51d..6d64eb72 100644 --- a/src/Command/PipeCommand.php +++ b/src/Command/PipeCommand.php @@ -5,7 +5,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class PipeCommand extends BaseCommand { +class PipeCommand extends CvCommand { /** * @param string|null $name diff --git a/src/Command/ScriptCommand.php b/src/Command/ScriptCommand.php index 41364e0f..df20c771 100644 --- a/src/Command/ScriptCommand.php +++ b/src/Command/ScriptCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ScriptCommand extends BaseCommand { +class ScriptCommand extends CvCommand { protected function configure() { $this diff --git a/src/Command/SettingGetCommand.php b/src/Command/SettingGetCommand.php index 9af13a4a..cf7e0458 100644 --- a/src/Command/SettingGetCommand.php +++ b/src/Command/SettingGetCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class SettingGetCommand extends BaseCommand { +class SettingGetCommand extends CvCommand { use StructuredOutputTrait; use SettingTrait; diff --git a/src/Command/SettingRevertCommand.php b/src/Command/SettingRevertCommand.php index c1ba4766..722210c9 100644 --- a/src/Command/SettingRevertCommand.php +++ b/src/Command/SettingRevertCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class SettingRevertCommand extends BaseCommand { +class SettingRevertCommand extends CvCommand { use StructuredOutputTrait; use SettingTrait; diff --git a/src/Command/SettingSetCommand.php b/src/Command/SettingSetCommand.php index 14f15f5f..cd717a0c 100644 --- a/src/Command/SettingSetCommand.php +++ b/src/Command/SettingSetCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class SettingSetCommand extends BaseCommand { +class SettingSetCommand extends CvCommand { use StructuredOutputTrait; use SettingTrait; diff --git a/src/Command/ShowCommand.php b/src/Command/ShowCommand.php index f33b3401..2f5eea5f 100644 --- a/src/Command/ShowCommand.php +++ b/src/Command/ShowCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ShowCommand extends BaseCommand { +class ShowCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/SqlCliCommand.php b/src/Command/SqlCliCommand.php index 65b29933..367af698 100644 --- a/src/Command/SqlCliCommand.php +++ b/src/Command/SqlCliCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class SqlCliCommand extends BaseCommand { +class SqlCliCommand extends CvCommand { protected function configure() { $this diff --git a/src/Command/UpgradeCommand.php b/src/Command/UpgradeCommand.php index cbf3e877..ca5b87a9 100644 --- a/src/Command/UpgradeCommand.php +++ b/src/Command/UpgradeCommand.php @@ -6,7 +6,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class UpgradeCommand extends BaseCommand { +class UpgradeCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/UpgradeDbCommand.php b/src/Command/UpgradeDbCommand.php index 37c64899..87be5804 100644 --- a/src/Command/UpgradeDbCommand.php +++ b/src/Command/UpgradeDbCommand.php @@ -10,7 +10,7 @@ /** * Command for asking CiviCRM for the appropriate tarball to download. */ -class UpgradeDbCommand extends BaseCommand { +class UpgradeDbCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/UpgradeDlCommand.php b/src/Command/UpgradeDlCommand.php index 7b1c7e62..d9482348 100644 --- a/src/Command/UpgradeDlCommand.php +++ b/src/Command/UpgradeDlCommand.php @@ -11,7 +11,7 @@ /** * Command for asking CiviCRM for the appropriate tarball to download. */ -class UpgradeDlCommand extends BaseCommand { +class UpgradeDlCommand extends CvCommand { use StructuredOutputTrait; diff --git a/src/Command/UpgradeGetCommand.php b/src/Command/UpgradeGetCommand.php index 6d2da3bc..5f4ff0ee 100644 --- a/src/Command/UpgradeGetCommand.php +++ b/src/Command/UpgradeGetCommand.php @@ -9,7 +9,7 @@ /** * Command for asking CiviCRM for the appropriate tarball to download. */ -class UpgradeGetCommand extends BaseCommand { +class UpgradeGetCommand extends CvCommand { const DEFAULT_CHECK_URL = "https://upgrade.civicrm.org/check"; // const DEFAULT_CHECK_URL = "http://civicrm-upgrade-manager.l/check"; diff --git a/src/Command/UpgradeReportCommand.php b/src/Command/UpgradeReportCommand.php index eaf9b367..366fcc2a 100644 --- a/src/Command/UpgradeReportCommand.php +++ b/src/Command/UpgradeReportCommand.php @@ -9,7 +9,7 @@ /** * Command for asking CiviCRM for the appropriate tarball to download. */ -class UpgradeReportCommand extends BaseCommand { +class UpgradeReportCommand extends CvCommand { const DEFAULT_REPORT_URL = 'https://upgrade.civicrm.org/report'; use StructuredOutputTrait; diff --git a/src/Command/UrlCommand.php b/src/Command/UrlCommand.php index 9ca5e336..a5a74936 100644 --- a/src/Command/UrlCommand.php +++ b/src/Command/UrlCommand.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class UrlCommand extends BaseCommand { +class UrlCommand extends CvCommand { use ExtensionTrait; use StructuredOutputTrait; diff --git a/tests/Command/BaseExtensionCommandTest.php b/tests/Command/BaseExtensionCommandTest.php index dc28ff0e..26f4a81a 100644 --- a/tests/Command/BaseExtensionCommandTest.php +++ b/tests/Command/BaseExtensionCommandTest.php @@ -37,7 +37,7 @@ public function repoOptionExamples() { * @dataProvider repoOptionExamples */ public function testParseRepo($inputArgv, $expectUrl) { - $c = new class('ext:example') extends BaseCommand { + $c = new class('ext:example') extends CvCommand { use ExtensionTrait; }; $c->configureRepoOptions(); diff --git a/tests/Plugin/FluentHelloPluginTest/hello.php b/tests/Plugin/FluentHelloPluginTest/hello.php index 8c5a36b7..b4bef8bf 100644 --- a/tests/Plugin/FluentHelloPluginTest/hello.php +++ b/tests/Plugin/FluentHelloPluginTest/hello.php @@ -1,7 +1,7 @@ addListener('cv.app.commands', function ($e) { - $e['commands'][] = (new BaseCommand('hello:normal')) + $e['commands'][] = (new CvCommand('hello:normal')) ->setDescription('Say a greeting') ->addArgument('name') ->setCode(function($input, $output) { @@ -39,7 +39,7 @@ throw new \RuntimeException("Argument \"name\" is inconsistent!"); } if (!Civi\Core\Container::isContainerBooted()) { - throw new \LogicException("Container should have been booted by BaseCommand!"); + throw new \LogicException("Container should have been booted by CvCommand!"); } $name = $input->getArgument('name') ?: 'world'; $output->writeln("Hey-yo $name via parameter!"); @@ -47,7 +47,7 @@ return 0; }); - $e['commands'][] = (new BaseCommand('hello:noboot')) + $e['commands'][] = (new CvCommand('hello:noboot')) ->setDescription('Say a greeting') ->addArgument('name') ->setBootOptions(['auto' => FALSE]) @@ -57,7 +57,7 @@ throw new \RuntimeException("Argument \"name\" is inconsistent!"); } if (class_exists('Civi\Core\Container')) { - throw new \LogicException("Container should not have been booted by BaseCommand!"); + throw new \LogicException("Container should not have been booted by CvCommand!"); } $name = $input->getArgument('name') ?: 'world'; $output->writeln("Hey-yo $name via parameter!");