diff --git a/.envrc b/.envrc new file mode 100644 index 000000000..6444c8560 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +export PATH="$PATH:${PWD}/vendor/bin" diff --git a/src/Attribute/RequireAuth.php b/src/Attribute/RequireAuth.php new file mode 100644 index 000000000..af6ca0c80 --- /dev/null +++ b/src/Attribute/RequireAuth.php @@ -0,0 +1,13 @@ +commandRequiresAuthentication() && !$this->cloudApiClientService->isMachineAuthenticated()) { + if ((new \ReflectionClass(static::class))->getAttributes(RequireAuth::class) && !$this->cloudApiClientService->isMachineAuthenticated()) { throw new AcquiaCliException('This machine is not yet authenticated with the Acquia Cloud Site Factory. Run `acli auth:acsf-login`'); } } diff --git a/src/Command/Acsf/AcsfListCommand.php b/src/Command/Acsf/AcsfListCommand.php index a8ab2816b..7262d17f8 100644 --- a/src/Command/Acsf/AcsfListCommand.php +++ b/src/Command/Acsf/AcsfListCommand.php @@ -4,16 +4,13 @@ namespace Acquia\Cli\Command\Acsf; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; -#[AsCommand(name: 'acsf:list')] -class AcsfListCommand extends AcsfListCommandBase { +#[RequireAuth] +#[AsCommand(name: 'acsf:list', description: 'List all Acquia Cloud Site Factory commands', aliases: ['acsf'])] +final class AcsfListCommand extends AcsfListCommandBase { protected string $namespace = 'acsf'; - protected function configure(): void { - $this->setDescription("List all Acquia Cloud Site Factory commands") - ->setAliases(['acsf']); - } - } diff --git a/src/Command/Acsf/AcsfListCommandBase.php b/src/Command/Acsf/AcsfListCommandBase.php index 25cdd9743..6da2bdbab 100644 --- a/src/Command/Acsf/AcsfListCommandBase.php +++ b/src/Command/Acsf/AcsfListCommandBase.php @@ -17,14 +17,6 @@ public function setNamespace(string $namespace): void { $this->namespace = $namespace; } - /** - * Indicates whether the command requires the machine to be authenticated with the Cloud Platform. - */ - protected function commandRequiresAuthentication(): bool { - // Assume commands require authentication unless they opt out by overriding this method. - return FALSE; - } - protected function execute(InputInterface $input, OutputInterface $output): int { $commands = $this->getApplication()->all(); foreach ($commands as $command) { diff --git a/src/Command/Api/ApiBaseCommand.php b/src/Command/Api/ApiBaseCommand.php index 39f0f4da8..b1c96921d 100644 --- a/src/Command/Api/ApiBaseCommand.php +++ b/src/Command/Api/ApiBaseCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Api; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use AcquiaCloudApi\Connector\Client; use AcquiaCloudApi\Exception\ApiErrorException; @@ -21,7 +22,8 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Validation; -#[AsCommand(name: 'api:base')] +#[RequireAuth] +#[AsCommand(name: 'api:base', hidden: TRUE)] class ApiBaseCommand extends CommandBase { protected string $method; @@ -53,11 +55,6 @@ class ApiBaseCommand extends CommandBase { */ private array $pathParams = []; - protected function configure(): void { - $this->setHidden(); - parent::configure(); - } - protected function interact(InputInterface $input, OutputInterface $output): void { $params = array_merge($this->queryParams, $this->postParams, $this->pathParams); foreach ($this->getDefinition()->getArguments() as $argument) { diff --git a/src/Command/Api/ApiListCommand.php b/src/Command/Api/ApiListCommand.php index 3d5eabc91..3f71a8c19 100644 --- a/src/Command/Api/ApiListCommand.php +++ b/src/Command/Api/ApiListCommand.php @@ -4,16 +4,13 @@ namespace Acquia\Cli\Command\Api; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; -#[AsCommand(name: 'api:list')] -class ApiListCommand extends ApiListCommandBase { +#[RequireAuth] +#[AsCommand(name: 'api:list', description: 'List all API commands', aliases: ['api'])] +final class ApiListCommand extends ApiListCommandBase { protected string $namespace = 'api'; - protected function configure(): void { - $this->setDescription("List all API commands") - ->setAliases(['api']); - } - } diff --git a/src/Command/App/AppOpenCommand.php b/src/Command/App/AppOpenCommand.php index 9a51ba0e2..7d78ec612 100644 --- a/src/Command/App/AppOpenCommand.php +++ b/src/Command/App/AppOpenCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\App; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use Symfony\Component\Console\Attribute\AsCommand; @@ -11,13 +12,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'app:open')] -class AppOpenCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'app:open', description: 'Opens your browser to view a given Cloud application', aliases: ['open', 'o'])] +final class AppOpenCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Opens your browser to view a given Cloud application') - ->acceptApplicationUuid() - ->setAliases(['open', 'o']); + $this + ->acceptApplicationUuid(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/App/AppVcsInfo.php b/src/Command/App/AppVcsInfo.php index 8be360d62..768f72522 100644 --- a/src/Command/App/AppVcsInfo.php +++ b/src/Command/App/AppVcsInfo.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\App; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use AcquiaCloudApi\Endpoints\Code; @@ -14,11 +15,12 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'app:vcs:info')] +#[RequireAuth] +#[AsCommand(name: 'app:vcs:info', description: 'Get all branches and tags of the application with the deployment status')] class AppVcsInfo extends CommandBase { protected function configure(): void { - $this->setDescription('Get all branches and tags of the application with the deployment status') + $this ->addOption('deployed', NULL, InputOption::VALUE_OPTIONAL, 'Show only deployed branches and tags') ->addUsage('[] --deployed'); $this->acceptApplicationUuid(); diff --git a/src/Command/App/LinkCommand.php b/src/Command/App/LinkCommand.php index 2d6108f01..d0c626a36 100644 --- a/src/Command/App/LinkCommand.php +++ b/src/Command/App/LinkCommand.php @@ -4,18 +4,18 @@ namespace Acquia\Cli\Command\App; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'app:link')] -class LinkCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'app:link', description: 'Associate your project with a Cloud Platform application', aliases: ['link'])] +final class LinkCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Associate your project with a Cloud Platform application') - ->setAliases(['link']); $this->acceptApplicationUuid(); } diff --git a/src/Command/App/LogTailCommand.php b/src/Command/App/LogTailCommand.php index 8e66908e3..d88c62bd2 100644 --- a/src/Command/App/LogTailCommand.php +++ b/src/Command/App/LogTailCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\App; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use AcquiaCloudApi\Endpoints\Logs; use Symfony\Component\Console\Attribute\AsCommand; @@ -11,13 +12,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'app:log:tail')] -class LogTailCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'app:log:tail', description: 'Tail the logs from your environments', aliases: ['tail', 'log:tail'])] +final class LogTailCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Tail the logs from your environments') - ->acceptEnvironmentId() - ->setAliases(['tail', 'log:tail']); + $this + ->acceptEnvironmentId(); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/App/NewCommand.php b/src/Command/App/NewCommand.php index 83f5f5bee..99a576c15 100644 --- a/src/Command/App/NewCommand.php +++ b/src/Command/App/NewCommand.php @@ -14,13 +14,12 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Path; -#[AsCommand(name: 'app:new:local')] -class NewCommand extends CommandBase { +#[AsCommand(name: 'app:new:local', description: 'Create a new Drupal or Next.js project', aliases: ['new'])] +final class NewCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Create a new Drupal or Next.js project') - ->addArgument('directory', InputArgument::OPTIONAL, 'The destination directory') - ->setAliases(['new']); + $this + ->addArgument('directory', InputArgument::OPTIONAL, 'The destination directory'); } protected function execute(InputInterface $input, OutputInterface $output): int { @@ -65,10 +64,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - private function createNextJsProject(string $dir): void { $process = $this->localMachineHelper->execute([ 'npx', diff --git a/src/Command/App/NewFromDrupal7Command.php b/src/Command/App/NewFromDrupal7Command.php index 7cf30ec2d..75c67ded4 100644 --- a/src/Command/App/NewFromDrupal7Command.php +++ b/src/Command/App/NewFromDrupal7Command.php @@ -22,8 +22,13 @@ use Symfony\Component\Filesystem\Path; use Symfony\Component\Validator\Exception\ValidatorException; -#[AsCommand(name: 'app:new:from:drupal7')] -class NewFromDrupal7Command extends CommandBase { +#[AsCommand(name: 'app:new:from:drupal7', description: 'Generate a new Drupal 9+ project from a Drupal 7 application using the default Acquia Migrate Accelerate recommendations.', aliases: [ + // Currently only "from Drupal 7", more to potentially follow. + 'from:d7', + // A nod to its roots. + 'ama', +])] +final class NewFromDrupal7Command extends CommandBase { /** * Exit code raised when the URI flag does not correspond to configuration. @@ -42,18 +47,12 @@ class NewFromDrupal7Command extends CommandBase { public const ERR_INDETERMINATE_SITE = 4; protected function configure(): void { - $this->setDescription('Generate a new Drupal 9+ project from a Drupal 7 application using the default Acquia Migrate Accelerate recommendations.') + $this ->addOption('drupal7-directory', 'source', InputOption::VALUE_OPTIONAL, 'The root of the Drupal 7 application') ->addOption('drupal7-uri', 'uri', InputOption::VALUE_OPTIONAL, 'Only necessary in case of a multisite. If a single site, this will be computed automatically.') ->addOption('stored-analysis', 'analysis', InputOption::VALUE_OPTIONAL, 'As an alternative to drupal7-directory, it is possible to pass a stored analysis.') ->addOption('recommendations', 'recommendations', InputOption::VALUE_OPTIONAL, 'Overrides the default recommendations.') - ->addOption('directory', 'destination', InputOption::VALUE_OPTIONAL, 'The directory where to generate the new application.') - ->setAliases([ - // Currently only "from Drupal 7", more to potentially follow. - 'from:d7', - // A nod to its roots. - 'ama', - ]); + ->addOption('directory', 'destination', InputOption::VALUE_OPTIONAL, 'The directory where to generate the new application.'); } private function getInspector(InputInterface $input): SiteInspectorInterface { @@ -215,10 +214,6 @@ function (mixed $path): string { return Command::SUCCESS; } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - private function initializeGitRepository(string $dir): void { if ($this->localMachineHelper->getFilesystem()->exists(Path::join($dir, '.git'))) { $this->logger->debug('.git directory detected, skipping Git repo initialization'); diff --git a/src/Command/App/TaskWaitCommand.php b/src/Command/App/TaskWaitCommand.php index e9ac1c9d0..501afb8c5 100644 --- a/src/Command/App/TaskWaitCommand.php +++ b/src/Command/App/TaskWaitCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\App; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -11,11 +12,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'app:task-wait')] -class TaskWaitCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'app:task-wait', description: 'Wait for a task to complete')] +final class TaskWaitCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Wait for a task to complete') + $this ->addArgument('notification-uuid', InputArgument::REQUIRED, 'The task notification UUID or Cloud Platform API response containing a linked notification') ->setHelp('Accepts either a notification UUID or Cloud Platform API response as JSON string. The JSON string must contain the _links->notification->href property.') ->addUsage('"$(acli api:environments:domain-clear-caches [environmentId] [domain])"'); diff --git a/src/Command/App/UnlinkCommand.php b/src/Command/App/UnlinkCommand.php index dad0de513..d7f922bb7 100644 --- a/src/Command/App/UnlinkCommand.php +++ b/src/Command/App/UnlinkCommand.php @@ -11,17 +11,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'app:unlink')] -class UnlinkCommand extends CommandBase { - - protected function configure(): void { - $this->setDescription('Remove local association between your project and a Cloud Platform application') - ->setAliases(['unlink']); - } - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } +#[AsCommand(name: 'app:unlink', description: 'Remove local association between your project and a Cloud Platform application', aliases: ['unlink'])] +final class UnlinkCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $this->validateCwdIsValidDrupalProject(); diff --git a/src/Command/Archive/ArchiveExportCommand.php b/src/Command/Archive/ArchiveExportCommand.php index 22fdb093b..e26f52301 100644 --- a/src/Command/Archive/ArchiveExportCommand.php +++ b/src/Command/Archive/ArchiveExportCommand.php @@ -4,11 +4,14 @@ namespace Acquia\Cli\Command\Archive; +use Acquia\Cli\Attribute\RequireAuth; +use Acquia\Cli\Attribute\RequireDb; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use Acquia\Cli\Output\Checklist; use Acquia\DrupalEnvironmentDetector\AcquiaDrupalEnvironmentDetector; use Closure; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -17,7 +20,10 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; -class ArchiveExportCommand extends CommandBase { +#[RequireAuth] +#[RequireDb] +#[AsCommand(name: 'archive:export', description: 'Export an archive of the Drupal application including code, files, and database')] +final class ArchiveExportCommand extends CommandBase { protected Checklist $checklist; @@ -30,13 +36,8 @@ class ArchiveExportCommand extends CommandBase { private const PUBLIC_FILES_DIR = '/docroot/sites/default/files'; - protected function commandRequiresDatabase(): bool { - return TRUE; - } - protected function configure(): void { - $this->setName('archive:export'); - $this->setDescription('Export an archive of the Drupal application including code, files, and database') + $this ->addArgument('destination-dir', InputArgument::REQUIRED, 'The destination directory for the archive file') ->addOption('source-dir', 'dir', InputOption::VALUE_REQUIRED, 'The directory containing the Drupal project to be pushed') ->addOption('no-files', NULL, InputOption::VALUE_NONE, 'Exclude public files directory from archive') diff --git a/src/Command/Auth/AuthAcsfLoginCommand.php b/src/Command/Auth/AuthAcsfLoginCommand.php index 7678e50b7..861a180fd 100644 --- a/src/Command/Auth/AuthAcsfLoginCommand.php +++ b/src/Command/Auth/AuthAcsfLoginCommand.php @@ -11,20 +11,16 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'auth:acsf-login')] -class AuthAcsfLoginCommand extends CommandBase { +#[AsCommand(name: 'auth:acsf-login', description: 'Register your Site Factory API key and secret to use API functionality')] +final class AuthAcsfLoginCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Register your Site Factory API key and secret to use API functionality') + $this ->addOption('username', 'u', InputOption::VALUE_REQUIRED, "Your Site Factory username") ->addOption('key', 'k', InputOption::VALUE_REQUIRED, "Your Site Factory key") ->addOption('factory-url', 'f', InputOption::VALUE_REQUIRED, "Your Site Factory URL"); } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('factory-url')) { $factoryUrl = $input->getOption('factory-url'); diff --git a/src/Command/Auth/AuthAcsfLogoutCommand.php b/src/Command/Auth/AuthAcsfLogoutCommand.php index b979871fa..171272e27 100644 --- a/src/Command/Auth/AuthAcsfLogoutCommand.php +++ b/src/Command/Auth/AuthAcsfLogoutCommand.php @@ -10,16 +10,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'auth:acsf-logout')] -class AuthAcsfLogoutCommand extends CommandBase { - - protected function configure(): void { - $this->setDescription('Remove your Site Factory key and secret from your local machine.'); - } - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } +#[AsCommand(name: 'auth:acsf-logout', description: 'Remove your Site Factory key and secret from your local machine.')] +final class AuthAcsfLogoutCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $factories = $this->datastoreCloud->get('acsf_factories'); diff --git a/src/Command/Auth/AuthLoginCommand.php b/src/Command/Auth/AuthLoginCommand.php index 48b4748f4..321665e83 100644 --- a/src/Command/Auth/AuthLoginCommand.php +++ b/src/Command/Auth/AuthLoginCommand.php @@ -11,20 +11,15 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'auth:login')] -class AuthLoginCommand extends CommandBase { +#[AsCommand(name: 'auth:login', description: 'Register your Cloud API key and secret to use API functionality', aliases: ['login'])] +final class AuthLoginCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Register your Cloud API key and secret to use API functionality') - ->setAliases(['login']) + $this ->addOption('key', 'k', InputOption::VALUE_REQUIRED, 'Your Cloud API key') ->addOption('secret', 's', InputOption::VALUE_REQUIRED, 'Your Cloud API secret'); } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->cloudApiClientService->isMachineAuthenticated()) { $answer = $this->io->confirm('Your machine has already been authenticated with the Cloud Platform API, would you like to re-authenticate?'); diff --git a/src/Command/Auth/AuthLogoutCommand.php b/src/Command/Auth/AuthLogoutCommand.php index b9eab222e..9edda39f7 100644 --- a/src/Command/Auth/AuthLogoutCommand.php +++ b/src/Command/Auth/AuthLogoutCommand.php @@ -10,17 +10,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'auth:logout')] -class AuthLogoutCommand extends CommandBase { - - protected function configure(): void { - $this->setDescription('Remove Cloud API key and secret from local machine.') - ->setAliases(['logout']); - } - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } +#[AsCommand(name: 'auth:logout', description: 'Remove Cloud API key and secret from local machine.', aliases: ['logout'])] +final class AuthLogoutCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->cloudApiClientService->isMachineAuthenticated()) { diff --git a/src/Command/CodeStudio/CodeStudioPhpVersionCommand.php b/src/Command/CodeStudio/CodeStudioPhpVersionCommand.php index 47582765d..64a9cf69c 100644 --- a/src/Command/CodeStudio/CodeStudioPhpVersionCommand.php +++ b/src/Command/CodeStudio/CodeStudioPhpVersionCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\CodeStudio; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Gitlab\Exception\RuntimeException; use Symfony\Component\Console\Attribute\AsCommand; @@ -11,13 +12,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'codestudio:php-version')] -class CodeStudioPhpVersionCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'codestudio:php-version', description: 'Change the PHP version in Code Studio')] +final class CodeStudioPhpVersionCommand extends CommandBase { use CodeStudioCommandTrait; protected function configure(): void { - $this->setDescription('Change the PHP version in Code Studio') + $this ->addArgument('php-version', InputArgument::REQUIRED, 'The PHP version that needs to configured or updated') ->addUsage('8.1 myapp') ->addUsage('8.1 abcd1234-1111-2222-3333-0e02b2c3d470'); diff --git a/src/Command/CodeStudio/CodeStudioPipelinesMigrateCommand.php b/src/Command/CodeStudio/CodeStudioPipelinesMigrateCommand.php index 869d13342..f8eb91cc7 100644 --- a/src/Command/CodeStudio/CodeStudioPipelinesMigrateCommand.php +++ b/src/Command/CodeStudio/CodeStudioPipelinesMigrateCommand.php @@ -16,18 +16,17 @@ use Symfony\Component\Filesystem\Path; use Symfony\Component\Yaml\Yaml; -#[AsCommand(name: 'codestudio:pipelines-migrate')] -class CodeStudioPipelinesMigrateCommand extends CommandBase { +#[AsCommand(name: 'codestudio:pipelines-migrate', description: 'Migrate .acquia-pipeline.yml file to .gitlab-ci.yml file for a given Acquia Cloud application', aliases: ['cs:pipelines-migrate'])] +final class CodeStudioPipelinesMigrateCommand extends CommandBase { use CodeStudioCommandTrait; protected function configure(): void { - $this->setDescription('Migrate .acquia-pipeline.yml file to .gitlab-ci.yml file for a given Acquia Cloud application') + $this ->addOption('key', NULL, InputOption::VALUE_REQUIRED, 'The Cloud Platform API token that Code Studio will use') ->addOption('secret', NULL, InputOption::VALUE_REQUIRED, 'The Cloud Platform API secret that Code Studio will use') ->addOption('gitlab-token', NULL, InputOption::VALUE_REQUIRED, 'The GitLab personal access token that will be used to communicate with the GitLab instance') - ->addOption('gitlab-project-id', NULL, InputOption::VALUE_REQUIRED, 'The project ID (an integer) of the GitLab project to configure.') - ->setAliases(['cs:pipelines-migrate']); + ->addOption('gitlab-project-id', NULL, InputOption::VALUE_REQUIRED, 'The project ID (an integer) of the GitLab project to configure.'); $this->acceptApplicationUuid(); $this->setHidden(!AcquiaDrupalEnvironmentDetector::isAhIdeEnv()); } @@ -75,10 +74,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - /** * Check whether wizard command is executed by checking the env variable of codestudio project. * diff --git a/src/Command/CodeStudio/CodeStudioWizardCommand.php b/src/Command/CodeStudio/CodeStudioWizardCommand.php index b47e14bdb..52675b696 100644 --- a/src/Command/CodeStudio/CodeStudioWizardCommand.php +++ b/src/Command/CodeStudio/CodeStudioWizardCommand.php @@ -15,21 +15,20 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'codestudio:wizard')] -class CodeStudioWizardCommand extends WizardCommandBase { +#[AsCommand(name: 'codestudio:wizard', description: 'Create and/or configure a new Code Studio project for a given Acquia Cloud application', aliases: ['cs:wizard'])] +final class CodeStudioWizardCommand extends WizardCommandBase { use CodeStudioCommandTrait; private Checklist $checklist; protected function configure(): void { - $this->setDescription('Create and/or configure a new Code Studio project for a given Acquia Cloud application') + $this ->addOption('key', NULL, InputOption::VALUE_REQUIRED, 'The Cloud Platform API token that Code Studio will use') ->addOption('secret', NULL, InputOption::VALUE_REQUIRED, 'The Cloud Platform API secret that Code Studio will use') ->addOption('gitlab-token', NULL, InputOption::VALUE_REQUIRED, 'The GitLab personal access token that will be used to communicate with the GitLab instance') ->addOption('gitlab-project-id', NULL, InputOption::VALUE_REQUIRED, 'The project ID (an integer) of the GitLab project to configure.') - ->addOption('gitlab-host-name', NULL, InputOption::VALUE_REQUIRED, 'The GitLab hostname.') - ->setAliases(['cs:wizard']); + ->addOption('gitlab-host-name', NULL, InputOption::VALUE_REQUIRED, 'The GitLab hostname.'); $this->acceptApplicationUuid(); } @@ -116,10 +115,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - /** * @param array $project * @return array|null diff --git a/src/Command/CommandBase.php b/src/Command/CommandBase.php index bff811383..73be130d9 100644 --- a/src/Command/CommandBase.php +++ b/src/Command/CommandBase.php @@ -5,6 +5,8 @@ namespace Acquia\Cli\Command; use Acquia\Cli\ApiCredentialsInterface; +use Acquia\Cli\Attribute\RequireAuth; +use Acquia\Cli\Attribute\RequireDb; use Acquia\Cli\CloudApi\ClientService; use Acquia\Cli\Command\Ssh\SshKeyCommandBase; use Acquia\Cli\DataStore\AcquiaCliDatastore; @@ -112,10 +114,10 @@ public function __construct( $this->setLocalDbName(); $this->setLocalDbHost(); parent::__construct(); - if ($this->commandRequiresAuthentication()) { + if ((new \ReflectionClass(static::class))->getAttributes(RequireAuth::class)) { $this->appendHelp('This command requires authentication via the Cloud Platform API.'); } - if ($this->commandRequiresDatabase()) { + if ((new \ReflectionClass(static::class))->getAttributes(RequireDb::class)) { $this->appendHelp('This command requires an active database connection. Set the following environment variables prior to running this command: ' . 'ACLI_DB_HOST, ACLI_DB_NAME, ACLI_DB_USER, ACLI_DB_PASSWORD'); } @@ -301,18 +303,6 @@ protected function acceptSite(): self { return $this; } - /** - * Indicates whether the command requires the machine to be authenticated with the Cloud Platform. - */ - protected function commandRequiresAuthentication(): bool { - // Assume commands require authentication unless they opt out by overriding this method. - return TRUE; - } - - protected function commandRequiresDatabase(): bool { - return FALSE; - } - /** * Prompts the user to choose from a list of available Cloud Platform * applications. @@ -1477,7 +1467,7 @@ protected function validateEnvironmentUuid(mixed $envUuidArgument, mixed $argume } protected function checkAuthentication(): void { - if ($this->commandRequiresAuthentication() && !$this->cloudApiClientService->isMachineAuthenticated()) { + if ((new \ReflectionClass(static::class))->getAttributes(RequireAuth::class) && !$this->cloudApiClientService->isMachineAuthenticated()) { throw new AcquiaCliException('This machine is not yet authenticated with the Cloud Platform. Run `acli auth:login`'); } } diff --git a/src/Command/DocsCommand.php b/src/Command/DocsCommand.php index 310aab66e..162e3e0d6 100644 --- a/src/Command/DocsCommand.php +++ b/src/Command/DocsCommand.php @@ -11,19 +11,15 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; -#[AsCommand(name: 'docs')] -class DocsCommand extends CommandBase { +#[AsCommand(name: 'docs', description: 'Open Acquia product documentation in a web browser')] +final class DocsCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Open Acquia product documentation in a web browser') + $this ->addArgument('product', InputArgument::OPTIONAL, 'Acquia Product Name') ->addUsage('acli'); } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function execute(InputInterface $input, OutputInterface $output): int { $acquiaProducts = [ 'Acquia CLI' => [ diff --git a/src/Command/Email/ConfigurePlatformEmailCommand.php b/src/Command/Email/ConfigurePlatformEmailCommand.php index 3c1917cb8..4bb3f4742 100644 --- a/src/Command/Email/ConfigurePlatformEmailCommand.php +++ b/src/Command/Email/ConfigurePlatformEmailCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Email; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use Acquia\Cli\Output\Checklist; @@ -25,14 +26,14 @@ use Symfony\Component\Validator\Validation; use Symfony\Component\Yaml\Yaml; -#[AsCommand(name: 'email:configure')] -class ConfigurePlatformEmailCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'email:configure', description: 'Configure Platform email for one or more applications', aliases: ['ec'])] +final class ConfigurePlatformEmailCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Configure Platform email for one or more applications') + $this ->addArgument('subscriptionUuid', InputArgument::OPTIONAL, 'The subscription UUID to register the domain with.') - ->setHelp('This command configures Platform Email for a domain in a subscription. It registers the domain with the subscription, associates the domain with an application or set of applications, and enables Platform Email for selected environments of these applications.') - ->setAliases(['ec']); + ->setHelp('This command configures Platform Email for a domain in a subscription. It registers the domain with the subscription, associates the domain with an application or set of applications, and enables Platform Email for selected environments of these applications.'); } protected function execute(InputInterface $input, OutputInterface $output): int { diff --git a/src/Command/Email/EmailInfoForSubscriptionCommand.php b/src/Command/Email/EmailInfoForSubscriptionCommand.php index 239ee919b..ba0229570 100644 --- a/src/Command/Email/EmailInfoForSubscriptionCommand.php +++ b/src/Command/Email/EmailInfoForSubscriptionCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Email; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use AcquiaCloudApi\Connector\Client; use AcquiaCloudApi\Response\SubscriptionResponse; @@ -18,11 +19,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'email:info')] -class EmailInfoForSubscriptionCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'email:info', description: 'Print information related to Platform Email set up in a subscription.')] +final class EmailInfoForSubscriptionCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Print information related to Platform Email set up in a subscription.') + $this ->addArgument('subscriptionUuid', InputArgument::OPTIONAL, 'The subscription UUID whose Platform Email configuration is to be checked.') ->setHelp('This command lists information related to Platform Email for a subscription, including which domains have been validated, which have not, and which applications have Platform Email domains associated.'); } diff --git a/src/Command/Env/EnvCertCreateCommand.php b/src/Command/Env/EnvCertCreateCommand.php index 2f8e4f8cb..bb3c1b8c4 100644 --- a/src/Command/Env/EnvCertCreateCommand.php +++ b/src/Command/Env/EnvCertCreateCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Env; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use AcquiaCloudApi\Endpoints\SslCertificates; use Symfony\Component\Console\Attribute\AsCommand; @@ -13,11 +14,12 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'env:certificate-create')] -class EnvCertCreateCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'env:certificate-create', description: 'Install an SSL certificate.')] +final class EnvCertCreateCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Install an SSL certificate.') + $this ->addArgument('certificate', InputArgument::REQUIRED, 'Filename of the SSL certificate being installed') ->addArgument('private-key', InputArgument::REQUIRED, 'Filename of the SSL private key') ->addOption('legacy', '', InputOption::VALUE_OPTIONAL, 'True for legacy certificates', FALSE) diff --git a/src/Command/Env/EnvCopyCronCommand.php b/src/Command/Env/EnvCopyCronCommand.php index d63f5ce65..d1a5a8df8 100644 --- a/src/Command/Env/EnvCopyCronCommand.php +++ b/src/Command/Env/EnvCopyCronCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Env; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use AcquiaCloudApi\Endpoints\Crons; use Exception; @@ -13,11 +14,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'env:cron-copy')] -class EnvCopyCronCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'env:cron-copy', description: 'Copy all cron tasks from one Acquia Cloud Platform environment to another')] +final class EnvCopyCronCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Copy all cron tasks from one Acquia Cloud Platform environment to another') + $this ->addArgument('source_env', InputArgument::REQUIRED, 'Alias of the source environment in the format `app-name.env` or the environment uuid') ->addArgument('dest_env', InputArgument::REQUIRED, 'Alias of the destination environment in the format `app-name.env` or the environment uuid') ->addUsage(' ') diff --git a/src/Command/Env/EnvCreateCommand.php b/src/Command/Env/EnvCreateCommand.php index 8903e7abf..ac22d29fe 100644 --- a/src/Command/Env/EnvCreateCommand.php +++ b/src/Command/Env/EnvCreateCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Env; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use Acquia\Cli\Output\Checklist; @@ -16,13 +17,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'env:create')] -class EnvCreateCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'env:create', description: 'Create a new Continuous Delivery Environment (CDE)')] +final class EnvCreateCommand extends CommandBase { private Checklist $checklist; protected function configure(): void { - $this->setDescription('Create a new Continuous Delivery Environment (CDE)'); $this->addArgument('label', InputArgument::REQUIRED, 'The label of the new environment'); $this->addArgument('branch', InputArgument::OPTIONAL, 'The vcs path (git branch name) to deploy to the new environment'); $this->acceptApplicationUuid(); diff --git a/src/Command/Env/EnvDeleteCommand.php b/src/Command/Env/EnvDeleteCommand.php index 68175b54e..0c527ecae 100644 --- a/src/Command/Env/EnvDeleteCommand.php +++ b/src/Command/Env/EnvDeleteCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Env; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use AcquiaCloudApi\Endpoints\Environments; @@ -13,11 +14,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'env:delete')] -class EnvDeleteCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'env:delete', description: 'Delete a Continuous Delivery Environment (CDE)')] +final class EnvDeleteCommand extends CommandBase { protected function configure(): void { - $this->setDescription('Delete a Continuous Delivery Environment (CDE)'); $this->acceptEnvironmentId(); } diff --git a/src/Command/Env/EnvMirrorCommand.php b/src/Command/Env/EnvMirrorCommand.php index f8d016c41..7a2038717 100644 --- a/src/Command/Env/EnvMirrorCommand.php +++ b/src/Command/Env/EnvMirrorCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Env; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Output\Checklist; use AcquiaCloudApi\Connector\Client; @@ -17,13 +18,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'env:mirror')] -class EnvMirrorCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'env:mirror', description: 'Makes one environment identical to another in terms of code, database, files, and configuration.')] +final class EnvMirrorCommand extends CommandBase { private Checklist $checklist; protected function configure(): void { - $this->setDescription('Makes one environment identical to another in terms of code, database, files, and configuration.'); $this->addArgument('source-environment', InputArgument::REQUIRED, 'The Cloud Platform source environment ID or alias') ->addUsage('[]') ->addUsage('myapp.dev') diff --git a/src/Command/HelloWorldCommand.php b/src/Command/HelloWorldCommand.php index 89a56642f..c3409f6cc 100644 --- a/src/Command/HelloWorldCommand.php +++ b/src/Command/HelloWorldCommand.php @@ -9,13 +9,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'hello-world')] -class HelloWorldCommand extends CommandBase { - - protected function configure(): void { - $this->setDescription('Test command used for asserting core functionality') - ->setHidden(); - } +#[AsCommand(name: 'hello-world', description: 'Test command used for asserting core functionality', hidden: TRUE)] +final class HelloWorldCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $this->io->success('Hello world!'); diff --git a/src/Command/Ide/IdeCreateCommand.php b/src/Command/Ide/IdeCreateCommand.php index 3b46a7c71..cc700248d 100644 --- a/src/Command/Ide/IdeCreateCommand.php +++ b/src/Command/Ide/IdeCreateCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Helpers\LoopHelper; use Acquia\Cli\Output\Checklist; use AcquiaCloudApi\Endpoints\Account; @@ -20,15 +21,15 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Validation; -#[AsCommand(name: 'ide:create')] -class IdeCreateCommand extends IdeCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:create', description: 'Create a Cloud IDE')] +final class IdeCreateCommand extends IdeCommandBase { private IdeResponse $ide; private Client $client; protected function configure(): void { - $this->setDescription('Create a Cloud IDE'); $this->acceptApplicationUuid(); $this->addOption('label', NULL, InputOption::VALUE_REQUIRED, 'The label for the IDE'); } diff --git a/src/Command/Ide/IdeDeleteCommand.php b/src/Command/Ide/IdeDeleteCommand.php index edbf0e4a5..aaae9d213 100644 --- a/src/Command/Ide/IdeDeleteCommand.php +++ b/src/Command/Ide/IdeDeleteCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Helpers\SshCommandTrait; use AcquiaCloudApi\Endpoints\Ides; use Symfony\Component\Console\Attribute\AsCommand; @@ -11,13 +12,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:delete')] -class IdeDeleteCommand extends IdeCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:delete', description: 'Delete a Cloud IDE')] +final class IdeDeleteCommand extends IdeCommandBase { use SshCommandTrait; protected function configure(): void { - $this->setDescription('Delete a Cloud IDE'); $this->acceptApplicationUuid(); // @todo Add option to accept an ide UUID. } diff --git a/src/Command/Ide/IdeInfoCommand.php b/src/Command/Ide/IdeInfoCommand.php index d2a530a92..026a4ddf7 100644 --- a/src/Command/Ide/IdeInfoCommand.php +++ b/src/Command/Ide/IdeInfoCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide; +use Acquia\Cli\Attribute\RequireAuth; use AcquiaCloudApi\Endpoints\Ides; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -11,11 +12,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:info')] -class IdeInfoCommand extends IdeCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:info', description: 'Print information about a Cloud IDE')] +final class IdeInfoCommand extends IdeCommandBase { protected function configure(): void { - $this->setDescription('Print information about a Cloud IDE'); $this->acceptApplicationUuid(); } diff --git a/src/Command/Ide/IdeListCommand.php b/src/Command/Ide/IdeListCommand.php index 8d255ec44..ea83d2214 100644 --- a/src/Command/Ide/IdeListCommand.php +++ b/src/Command/Ide/IdeListCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide; +use Acquia\Cli\Attribute\RequireAuth; use AcquiaCloudApi\Endpoints\Ides; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -12,12 +13,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:list:app')] -class IdeListCommand extends IdeCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:list:app', description: 'List available Cloud IDEs belonging to a given application', aliases: ['ide:list'])] +final class IdeListCommand extends IdeCommandBase { protected function configure(): void { - $this->setDescription('List available Cloud IDEs belonging to a given application'); - $this->setAliases(['ide:list']); $this->acceptApplicationUuid(); } diff --git a/src/Command/Ide/IdeListMineCommand.php b/src/Command/Ide/IdeListMineCommand.php index 53ceca4d4..7e1409b0f 100644 --- a/src/Command/Ide/IdeListMineCommand.php +++ b/src/Command/Ide/IdeListMineCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide; +use Acquia\Cli\Attribute\RequireAuth; use AcquiaCloudApi\Endpoints\Applications; use AcquiaCloudApi\Endpoints\Ides; use Symfony\Component\Console\Attribute\AsCommand; @@ -13,12 +14,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:list:mine')] -class IdeListMineCommand extends IdeCommandBase { - - protected function configure(): void { - $this->setDescription('List Cloud IDEs belonging to you'); - } +#[RequireAuth] +#[AsCommand(name: 'ide:list:mine', description: 'List Cloud IDEs belonging to you')] +final class IdeListMineCommand extends IdeCommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $acquiaCloudClient = $this->cloudApiClientService->getClient(); diff --git a/src/Command/Ide/IdeOpenCommand.php b/src/Command/Ide/IdeOpenCommand.php index 5c30d90a6..0d56f7eca 100644 --- a/src/Command/Ide/IdeOpenCommand.php +++ b/src/Command/Ide/IdeOpenCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\DrupalEnvironmentDetector\AcquiaDrupalEnvironmentDetector; use AcquiaCloudApi\Endpoints\Ides; use Symfony\Component\Console\Attribute\AsCommand; @@ -11,11 +12,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:open')] -class IdeOpenCommand extends IdeCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:open', description: 'Open a Cloud IDE in your browser')] +final class IdeOpenCommand extends IdeCommandBase { protected function configure(): void { - $this->setDescription('Open a Cloud IDE in your browser') + $this ->setHidden(AcquiaDrupalEnvironmentDetector::isAhIdeEnv()); $this->acceptApplicationUuid(); // @todo Add option to accept an ide UUID. diff --git a/src/Command/Ide/IdePhpVersionCommand.php b/src/Command/Ide/IdePhpVersionCommand.php index 7ca48edef..c647eb000 100644 --- a/src/Command/Ide/IdePhpVersionCommand.php +++ b/src/Command/Ide/IdePhpVersionCommand.php @@ -12,22 +12,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:php-version')] -class IdePhpVersionCommand extends IdeCommandBase { +#[AsCommand(name: 'ide:php-version', description: 'Change the PHP version in the current IDE')] +final class IdePhpVersionCommand extends IdeCommandBase { private string $idePhpFilePathPrefix; - /* - * @param \Symfony\Component\Console\Input\InputInterface $input - * - * @return bool - */ - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function configure(): void { - $this->setDescription('Change the PHP version in the current IDE') + $this ->addArgument('version', InputArgument::REQUIRED, 'The PHP version') ->setHidden(!AcquiaDrupalEnvironmentDetector::isAhIdeEnv()); } diff --git a/src/Command/Ide/IdeServiceRestartCommand.php b/src/Command/Ide/IdeServiceRestartCommand.php index 9d3517c45..ca039d8d9 100644 --- a/src/Command/Ide/IdeServiceRestartCommand.php +++ b/src/Command/Ide/IdeServiceRestartCommand.php @@ -14,15 +14,11 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Validation; -#[AsCommand(name: 'ide:service-restart')] -class IdeServiceRestartCommand extends IdeCommandBase { - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } +#[AsCommand(name: 'ide:service-restart', description: 'Restart a service in the Cloud IDE')] +final class IdeServiceRestartCommand extends IdeCommandBase { protected function configure(): void { - $this->setDescription('Restart a service in the Cloud IDE') + $this ->addArgument('service', InputArgument::REQUIRED, 'The name of the service to restart') ->addUsage('php') ->addUsage('apache') diff --git a/src/Command/Ide/IdeServiceStartCommand.php b/src/Command/Ide/IdeServiceStartCommand.php index 8bb63bc8f..5d3f0d607 100644 --- a/src/Command/Ide/IdeServiceStartCommand.php +++ b/src/Command/Ide/IdeServiceStartCommand.php @@ -14,15 +14,11 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Validation; -#[AsCommand(name: 'ide:service-start')] -class IdeServiceStartCommand extends IdeCommandBase { - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } +#[AsCommand(name: 'ide:service-start', description: 'Start a service in the Cloud IDE')] +final class IdeServiceStartCommand extends IdeCommandBase { protected function configure(): void { - $this->setDescription('Start a service in the Cloud IDE') + $this ->addArgument('service', InputArgument::REQUIRED, 'The name of the service to start') ->addUsage('php') ->addUsage('apache') diff --git a/src/Command/Ide/IdeServiceStopCommand.php b/src/Command/Ide/IdeServiceStopCommand.php index fc0c1c26d..d0e9476d8 100644 --- a/src/Command/Ide/IdeServiceStopCommand.php +++ b/src/Command/Ide/IdeServiceStopCommand.php @@ -14,15 +14,11 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Validation; -#[AsCommand(name: 'ide:service-stop')] -class IdeServiceStopCommand extends IdeCommandBase { - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } +#[AsCommand(name: 'ide:service-stop', description: 'Stop a service in the Cloud IDE')] +final class IdeServiceStopCommand extends IdeCommandBase { protected function configure(): void { - $this->setDescription('Stop a service in the Cloud IDE') + $this ->addArgument('service', InputArgument::REQUIRED, 'The name of the service to stop') ->addUsage('php') ->addUsage('apache') diff --git a/src/Command/Ide/IdeShareCommand.php b/src/Command/Ide/IdeShareCommand.php index 2ae12137e..5d671b601 100644 --- a/src/Command/Ide/IdeShareCommand.php +++ b/src/Command/Ide/IdeShareCommand.php @@ -14,20 +14,16 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:share')] -class IdeShareCommand extends CommandBase { +#[AsCommand(name: 'ide:share', description: 'Get the share URL for a Cloud IDE')] +final class IdeShareCommand extends CommandBase { /** * @var array */ private array $shareCodeFilepaths; - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function configure(): void { - $this->setDescription('Get the share URL for a Cloud IDE') + $this ->addOption('regenerate', '', InputOption::VALUE_NONE, 'regenerate the share code') ->setHidden(!AcquiaDrupalEnvironmentDetector::isAhIdeEnv()); } diff --git a/src/Command/Ide/IdeXdebugToggleCommand.php b/src/Command/Ide/IdeXdebugToggleCommand.php index 51412bc9f..a003ca2ea 100644 --- a/src/Command/Ide/IdeXdebugToggleCommand.php +++ b/src/Command/Ide/IdeXdebugToggleCommand.php @@ -11,18 +11,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:xdebug-toggle')] -class IdeXdebugToggleCommand extends IdeCommandBase { +#[AsCommand(name: 'ide:xdebug-toggle', description: 'Toggle Xdebug on or off in the current IDE', aliases: ['xdebug'])] +final class IdeXdebugToggleCommand extends IdeCommandBase { private ?bool $xDebugEnabled; - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function configure(): void { - $this->setDescription('Toggle Xdebug on or off in the current IDE') - ->setAliases(['xdebug']) + $this ->setHidden(!AcquiaDrupalEnvironmentDetector::isAhIdeEnv()); } diff --git a/src/Command/Ide/Wizard/IdeWizardCreateSshKeyCommand.php b/src/Command/Ide/Wizard/IdeWizardCreateSshKeyCommand.php index a04c8992f..a77785a93 100644 --- a/src/Command/Ide/Wizard/IdeWizardCreateSshKeyCommand.php +++ b/src/Command/Ide/Wizard/IdeWizardCreateSshKeyCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide\Wizard; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Output\Checklist; use AcquiaCloudApi\Endpoints\Account; @@ -12,12 +13,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:wizard:ssh-key:create-upload')] -class IdeWizardCreateSshKeyCommand extends IdeWizardCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:wizard:ssh-key:create-upload', description: 'Wizard to perform first time setup tasks within an IDE', aliases: ['ide:wizard'])] +final class IdeWizardCreateSshKeyCommand extends IdeWizardCommandBase { protected function configure(): void { - $this->setDescription('Wizard to perform first time setup tasks within an IDE') - ->setAliases(['ide:wizard']) + $this ->setHidden(!CommandBase::isAcquiaCloudIde()); } diff --git a/src/Command/Ide/Wizard/IdeWizardDeleteSshKeyCommand.php b/src/Command/Ide/Wizard/IdeWizardDeleteSshKeyCommand.php index 78acc380c..97a4c87bf 100644 --- a/src/Command/Ide/Wizard/IdeWizardDeleteSshKeyCommand.php +++ b/src/Command/Ide/Wizard/IdeWizardDeleteSshKeyCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ide\Wizard; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Exception\AcquiaCliException; use Acquia\Cli\Helpers\SshCommandTrait; @@ -12,13 +13,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ide:wizard:ssh-key:delete')] -class IdeWizardDeleteSshKeyCommand extends IdeWizardCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ide:wizard:ssh-key:delete', description: 'Wizard to delete SSH key for IDE from Cloud')] +final class IdeWizardDeleteSshKeyCommand extends IdeWizardCommandBase { use SshCommandTrait; protected function configure(): void { - $this->setDescription('Wizard to delete SSH key for IDE from Cloud') + $this ->setHidden(!CommandBase::isAcquiaCloudIde()); } diff --git a/src/Command/Pull/PullCodeCommand.php b/src/Command/Pull/PullCodeCommand.php index 72226c866..aa38ea27f 100644 --- a/src/Command/Pull/PullCodeCommand.php +++ b/src/Command/Pull/PullCodeCommand.php @@ -4,6 +4,8 @@ namespace Acquia\Cli\Command\Pull; +use Acquia\Cli\Attribute\RequireAuth; +use Acquia\Cli\Attribute\RequireDb; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -11,15 +13,13 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'pull:code')] -class PullCodeCommand extends PullCommandBase { - - protected function commandRequiresDatabase(): bool { - return TRUE; - } +#[RequireAuth] +#[RequireDb] +#[AsCommand(name: 'pull:code', description: 'Copy code from a Cloud Platform environment')] +final class PullCodeCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Copy code from a Cloud Platform environment') + $this ->acceptEnvironmentId() ->addOption('dir', NULL, InputArgument::OPTIONAL, 'The directory containing the Drupal project to be refreshed') ->addOption('no-scripts', NULL, InputOption::VALUE_NONE, diff --git a/src/Command/Pull/PullCommand.php b/src/Command/Pull/PullCommand.php index 36f9f824e..da45900de 100644 --- a/src/Command/Pull/PullCommand.php +++ b/src/Command/Pull/PullCommand.php @@ -4,6 +4,8 @@ namespace Acquia\Cli\Command\Pull; +use Acquia\Cli\Attribute\RequireAuth; +use Acquia\Cli\Attribute\RequireDb; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -11,16 +13,13 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'pull:all')] -class PullCommand extends PullCommandBase { - - protected function commandRequiresDatabase(): bool { - return TRUE; - } +#[RequireAuth] +#[RequireDb] +#[AsCommand(name: 'pull:all', description: 'Copy code, database, and files from a Cloud Platform environment', aliases: ['refresh', 'pull'])] +final class PullCommand extends PullCommandBase { protected function configure(): void { - $this->setAliases(['refresh', 'pull']) - ->setDescription('Copy code, database, and files from a Cloud Platform environment') + $this ->acceptEnvironmentId() ->acceptSite() ->addOption('dir', NULL, InputArgument::OPTIONAL, 'The directory containing the Drupal project to be refreshed') diff --git a/src/Command/Pull/PullDatabaseCommand.php b/src/Command/Pull/PullDatabaseCommand.php index 5d5dd3268..516528de6 100644 --- a/src/Command/Pull/PullDatabaseCommand.php +++ b/src/Command/Pull/PullDatabaseCommand.php @@ -4,23 +4,22 @@ namespace Acquia\Cli\Command\Pull; +use Acquia\Cli\Attribute\RequireAuth; +use Acquia\Cli\Attribute\RequireDb; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'pull:database')] -class PullDatabaseCommand extends PullCommandBase { - - protected function commandRequiresDatabase(): bool { - return TRUE; - } +#[RequireAuth] +#[RequireDb] +#[AsCommand(name: 'pull:database', description: 'Import database backup from a Cloud Platform environment', aliases: ['pull:db'])] +final class PullDatabaseCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Import database backup from a Cloud Platform environment') + $this ->setHelp('This uses the latest available database backup, which may be up to 24 hours old. If no backup exists, one will be created.') - ->setAliases(['pull:db']) ->acceptEnvironmentId() ->acceptSite() ->addOption('no-scripts', NULL, InputOption::VALUE_NONE, diff --git a/src/Command/Pull/PullFilesCommand.php b/src/Command/Pull/PullFilesCommand.php index cc2190145..c0f4e9d34 100644 --- a/src/Command/Pull/PullFilesCommand.php +++ b/src/Command/Pull/PullFilesCommand.php @@ -4,16 +4,18 @@ namespace Acquia\Cli\Command\Pull; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'pull:files')] -class PullFilesCommand extends PullCommandBase { +#[RequireAuth] +#[AsCommand(name: 'pull:files', description: 'Copy Drupal public files from a Cloud Platform environment to your local environment')] +final class PullFilesCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Copy Drupal public files from a Cloud Platform environment to your local environment') + $this ->acceptEnvironmentId() ->acceptSite(); } diff --git a/src/Command/Pull/PullScriptsCommand.php b/src/Command/Pull/PullScriptsCommand.php index ffd174fbc..98965a1c0 100644 --- a/src/Command/Pull/PullScriptsCommand.php +++ b/src/Command/Pull/PullScriptsCommand.php @@ -10,19 +10,15 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'pull:run-scripts')] -class PullScriptsCommand extends PullCommandBase { +#[AsCommand(name: 'pull:run-scripts', description: 'Execute post pull scripts')] +final class PullScriptsCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Execute post pull scripts') + $this ->acceptEnvironmentId() ->addOption('dir', NULL, InputArgument::OPTIONAL, 'The directory containing the Drupal project to be refreshed'); } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function execute(InputInterface $input, OutputInterface $output): int { $this->executeAllScripts($input, $this->getOutputCallback($output, $this->checklist)); diff --git a/src/Command/Push/PushArtifactCommand.php b/src/Command/Push/PushArtifactCommand.php index 544ed196f..7b2c8ca70 100644 --- a/src/Command/Push/PushArtifactCommand.php +++ b/src/Command/Push/PushArtifactCommand.php @@ -16,8 +16,8 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Path; -#[AsCommand(name: 'push:artifact')] -class PushArtifactCommand extends PullCommandBase { +#[AsCommand(name: 'push:artifact', description: 'Build and push a code artifact to a Cloud Platform environment')] +final class PushArtifactCommand extends PullCommandBase { /** * Composer vendor directories. @@ -40,7 +40,7 @@ class PushArtifactCommand extends PullCommandBase { private string $destinationGitRef; protected function configure(): void { - $this->setDescription('Build and push a code artifact to a Cloud Platform environment') + $this ->addOption('dir', NULL, InputArgument::OPTIONAL, 'The directory containing the Drupal project to be pushed') ->addOption('no-sanitize', NULL, InputOption::VALUE_NONE, 'Do not sanitize the build artifact') ->addOption('dry-run', NULL, InputOption::VALUE_NONE, 'Deprecated: Use no-push instead') @@ -60,10 +60,6 @@ protected function configure(): void { ->addUsage('--destination-git-urls=example@svn-1.prod.hosting.acquia.com:example.git --destination-git-branch=main-build'); } - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - protected function execute(InputInterface $input, OutputInterface $output): int { $this->setDirAndRequireProjectCwd($input); if ($input->getOption('no-clone')) { diff --git a/src/Command/Push/PushCodeCommand.php b/src/Command/Push/PushCodeCommand.php index 7cbab38ef..49c9cbc69 100644 --- a/src/Command/Push/PushCodeCommand.php +++ b/src/Command/Push/PushCodeCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Push; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\Pull\PullCommandBase; use Acquia\DrupalEnvironmentDetector\AcquiaDrupalEnvironmentDetector; use Symfony\Component\Console\Attribute\AsCommand; @@ -11,11 +12,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'push:code')] -class PushCodeCommand extends PullCommandBase { +#[RequireAuth] +#[AsCommand(name: 'push:code', description: 'Push code from your IDE to a Cloud Platform environment')] +final class PushCodeCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Push code from your IDE to a Cloud Platform environment') + $this ->setHidden(!AcquiaDrupalEnvironmentDetector::isAhIdeEnv() && !self::isLandoEnv()); } diff --git a/src/Command/Push/PushDatabaseCommand.php b/src/Command/Push/PushDatabaseCommand.php index db941c5eb..00298cac9 100644 --- a/src/Command/Push/PushDatabaseCommand.php +++ b/src/Command/Push/PushDatabaseCommand.php @@ -4,6 +4,8 @@ namespace Acquia\Cli\Command\Push; +use Acquia\Cli\Attribute\RequireAuth; +use Acquia\Cli\Attribute\RequireDb; use Acquia\Cli\Command\Pull\PullCommandBase; use Acquia\Cli\Exception\AcquiaCliException; use Acquia\Cli\Output\Checklist; @@ -14,16 +16,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'push:database')] -class PushDatabaseCommand extends PullCommandBase { - - protected function commandRequiresDatabase(): bool { - return TRUE; - } +#[RequireAuth] +#[RequireDb] +#[AsCommand(name: 'push:database', description: 'Push a database from your local environment to a Cloud Platform environment', aliases: ['push:db'])] +final class PushDatabaseCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Push a database from your local environment to a Cloud Platform environment') - ->setAliases(['push:db']) + $this ->acceptEnvironmentId() ->acceptSite(); } diff --git a/src/Command/Push/PushFilesCommand.php b/src/Command/Push/PushFilesCommand.php index 9b5ca49cd..e2ff087f9 100644 --- a/src/Command/Push/PushFilesCommand.php +++ b/src/Command/Push/PushFilesCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Push; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\Pull\PullCommandBase; use Acquia\Cli\Output\Checklist; use AcquiaCloudApi\Response\EnvironmentResponse; @@ -12,11 +13,12 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'push:files')] -class PushFilesCommand extends PullCommandBase { +#[RequireAuth] +#[AsCommand(name: 'push:files', description: 'Copy Drupal public files from your local environment to a Cloud Platform environment')] +final class PushFilesCommand extends PullCommandBase { protected function configure(): void { - $this->setDescription('Copy Drupal public files from your local environment to a Cloud Platform environment') + $this ->acceptEnvironmentId() ->acceptSite(); } diff --git a/src/Command/Remote/AliasListCommand.php b/src/Command/Remote/AliasListCommand.php index ea9595b5f..21c239f2a 100644 --- a/src/Command/Remote/AliasListCommand.php +++ b/src/Command/Remote/AliasListCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Remote; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use AcquiaCloudApi\Endpoints\Applications; use AcquiaCloudApi\Endpoints\Environments; @@ -13,12 +14,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'remote:aliases:list')] -class AliasListCommand extends CommandBase { +#[RequireAuth] +#[AsCommand(name: 'remote:aliases:list', description: 'List all aliases for the Cloud Platform environments', aliases: ['aliases', 'sa'])] +final class AliasListCommand extends CommandBase { protected function configure(): void { - $this->setDescription('List all aliases for the Cloud Platform environments') - ->setAliases(['aliases', 'sa']); $this->acceptApplicationUuid(); } diff --git a/src/Command/Remote/AliasesDownloadCommand.php b/src/Command/Remote/AliasesDownloadCommand.php index e74f448d5..4f9ff0cab 100644 --- a/src/Command/Remote/AliasesDownloadCommand.php +++ b/src/Command/Remote/AliasesDownloadCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Remote; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Exception\AcquiaCliException; use AcquiaCloudApi\Connector\Client; use AcquiaCloudApi\Endpoints\Account; @@ -20,13 +21,14 @@ /** * A command to proxy Drush commands on an environment using SSH. */ -#[AsCommand(name: 'remote:aliases:download')] -class AliasesDownloadCommand extends SshCommand { +#[RequireAuth] +#[AsCommand(name: 'remote:aliases:download', description: 'Download Drush aliases for the Cloud Platform')] +final class AliasesDownloadCommand extends SshBaseCommand { private string $drushArchiveFilepath; protected function configure(): void { - $this->setDescription('Download Drush aliases for the Cloud Platform') + $this ->addOption('destination-dir', NULL, InputOption::VALUE_REQUIRED, 'The directory to which aliases will be downloaded') ->addOption('all', NULL, InputOption::VALUE_NONE, 'Download the aliases for all applications that you have access to, not just the current one.'); $this->acceptApplicationUuid(); diff --git a/src/Command/Remote/DrushCommand.php b/src/Command/Remote/DrushCommand.php index 441818ff7..6a3761fa2 100644 --- a/src/Command/Remote/DrushCommand.php +++ b/src/Command/Remote/DrushCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Remote; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -12,12 +13,12 @@ /** * A command to proxy Drush commands on an environment using SSH. */ -#[AsCommand(name: 'remote:drush')] -class DrushCommand extends SshBaseCommand { +#[RequireAuth] +#[AsCommand(name: 'remote:drush', description: 'Run a Drush command remotely on a application\'s environment', aliases: ['drush', 'dr'])] +final class DrushCommand extends SshBaseCommand { protected function configure(): void { - $this->setAliases(['drush', 'dr']) - ->setDescription('Run a Drush command remotely on a application\'s environment') + $this ->setHelp('Pay close attention to the argument syntax! Note the usage of -- to separate the drush command arguments and options.') ->addArgument('alias', InputArgument::REQUIRED, 'Alias for application & environment in the format `app-name.env`') ->addArgument('drush_command', InputArgument::IS_ARRAY, 'Drush command') diff --git a/src/Command/Remote/SshCommand.php b/src/Command/Remote/SshCommand.php index c868af4f6..f924406bc 100644 --- a/src/Command/Remote/SshCommand.php +++ b/src/Command/Remote/SshCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Remote; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Exception\AcquiaCliException; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputArgument; @@ -13,12 +14,12 @@ /** * A command to proxy Drush commands on an environment using SSH. */ -#[AsCommand(name: 'remote:ssh')] -class SshCommand extends SshBaseCommand { +#[RequireAuth] +#[AsCommand(name: 'remote:ssh', description: 'Use SSH to open a shell or run a command in a Cloud Platform environment', aliases: ['ssh'])] +final class SshCommand extends SshBaseCommand { protected function configure(): void { - $this->setDescription('Use SSH to open a shell or run a command in a Cloud Platform environment') - ->setAliases(['ssh']) + $this ->addArgument('alias', InputArgument::REQUIRED, 'Alias for application & environment in the format `app-name.env`') ->addArgument('ssh_command', InputArgument::IS_ARRAY, 'Command to run via SSH (if not provided, opens a shell in the site directory)') ->addUsage("myapp.dev # open a shell in the myapp.dev environment") diff --git a/src/Command/Self/ClearCacheCommand.php b/src/Command/Self/ClearCacheCommand.php index b973f9131..1052e3a2e 100644 --- a/src/Command/Self/ClearCacheCommand.php +++ b/src/Command/Self/ClearCacheCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Self; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -12,13 +13,9 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; -#[AsCommand(name: 'self:clear-caches')] -class ClearCacheCommand extends CommandBase { - - protected function configure(): void { - $this->setDescription('Clears local Acquia CLI caches') - ->setAliases(['cc', 'cr']); - } +#[RequireAuth] +#[AsCommand(name: 'self:clear-caches', description: 'Clears local Acquia CLI caches', aliases: ['cc', 'cr'])] +final class ClearCacheCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { self::clearCaches(); diff --git a/src/Command/Self/ListCommand.php b/src/Command/Self/ListCommand.php index 98f7481ac..4b429c807 100644 --- a/src/Command/Self/ListCommand.php +++ b/src/Command/Self/ListCommand.php @@ -6,18 +6,14 @@ use Acquia\Cli\Command\Acsf\AcsfListCommandBase; use Acquia\Cli\Command\Api\ApiListCommandBase; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ListCommand extends \Symfony\Component\Console\Command\ListCommand { - - protected function configure(): void { - parent::configure(); - $this->setName('self:list') - ->setAliases(['list']); - } +#[AsCommand(name: 'list', description: NULL, aliases: ['self:list'])] +final class ListCommand extends \Symfony\Component\Console\Command\ListCommand { protected function execute(InputInterface $input, OutputInterface $output): int { foreach (['api', 'acsf'] as $prefix) { diff --git a/src/Command/Self/MakeDocsCommand.php b/src/Command/Self/MakeDocsCommand.php index 743c26f85..c37b562a5 100644 --- a/src/Command/Self/MakeDocsCommand.php +++ b/src/Command/Self/MakeDocsCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Self; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\CommandBase; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -11,13 +12,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'self:make-docs')] -class MakeDocsCommand extends CommandBase { - - protected function configure(): void { - $this->setDescription('Generate documentation for all ACLI commands') - ->setHidden(); - } +#[RequireAuth] +#[AsCommand(name: 'self:make-docs', description: 'Generate documentation for all ACLI commands', hidden: TRUE)] +final class MakeDocsCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $helper = new DescriptorHelper(); diff --git a/src/Command/Self/TelemetryCommand.php b/src/Command/Self/TelemetryCommand.php index 97c1f27ae..6ebc29aa2 100644 --- a/src/Command/Self/TelemetryCommand.php +++ b/src/Command/Self/TelemetryCommand.php @@ -11,17 +11,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'self:telemetry:toggle')] -class TelemetryCommand extends CommandBase { - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - - protected function configure(): void { - $this->setDescription('Toggle anonymous sharing of usage and performance data') - ->setAliases(['telemetry']); - } +#[AsCommand(name: 'self:telemetry:toggle', description: 'Toggle anonymous sharing of usage and performance data', aliases: ['telemetry'])] +final class TelemetryCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $datastore = $this->datastoreCloud; diff --git a/src/Command/Self/TelemetryDisableCommand.php b/src/Command/Self/TelemetryDisableCommand.php index 8efc5ceb1..2c757f031 100644 --- a/src/Command/Self/TelemetryDisableCommand.php +++ b/src/Command/Self/TelemetryDisableCommand.php @@ -11,17 +11,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'self:telemetry:disable')] -class TelemetryDisableCommand extends CommandBase { - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - - protected function configure(): void { - $this->setDescription('Disable anonymous sharing of usage and performance data') - ->setAliases(['telemetry:disable']); - } +#[AsCommand(name: 'self:telemetry:disable', description: 'Disable anonymous sharing of usage and performance data', aliases: ['telemetry:disable'])] +final class TelemetryDisableCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $datastore = $this->datastoreCloud; diff --git a/src/Command/Self/TelemetryEnableCommand.php b/src/Command/Self/TelemetryEnableCommand.php index 4b2763fc5..aec834d8e 100644 --- a/src/Command/Self/TelemetryEnableCommand.php +++ b/src/Command/Self/TelemetryEnableCommand.php @@ -11,17 +11,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'self:telemetry:enable')] -class TelemetryEnableCommand extends CommandBase { - - protected function commandRequiresAuthentication(): bool { - return FALSE; - } - - protected function configure(): void { - $this->setDescription('Enable anonymous sharing of usage and performance data') - ->setAliases(['telemetry:enable']); - } +#[AsCommand(name: 'self:telemetry:enable', description: 'Enable anonymous sharing of usage and performance data', aliases: ['telemetry:enable'])] +final class TelemetryEnableCommand extends CommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $datastore = $this->datastoreCloud; diff --git a/src/Command/Ssh/SshKeyCreateCommand.php b/src/Command/Ssh/SshKeyCreateCommand.php index 19ad6d63e..8b8892d91 100644 --- a/src/Command/Ssh/SshKeyCreateCommand.php +++ b/src/Command/Ssh/SshKeyCreateCommand.php @@ -4,17 +4,19 @@ namespace Acquia\Cli\Command\Ssh; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ssh-key:create')] -class SshKeyCreateCommand extends SshKeyCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ssh-key:create', description: 'Create an SSH key on your local machine')] +final class SshKeyCreateCommand extends SshKeyCommandBase { protected function configure(): void { - $this->setDescription('Create an SSH key on your local machine') + $this ->addOption('filename', NULL, InputOption::VALUE_REQUIRED, 'The filename of the SSH key') ->addOption('password', NULL, InputOption::VALUE_REQUIRED, 'The password for the SSH key'); } diff --git a/src/Command/Ssh/SshKeyCreateUploadCommand.php b/src/Command/Ssh/SshKeyCreateUploadCommand.php index 94e2ede4b..f49b2c4a5 100644 --- a/src/Command/Ssh/SshKeyCreateUploadCommand.php +++ b/src/Command/Ssh/SshKeyCreateUploadCommand.php @@ -4,17 +4,19 @@ namespace Acquia\Cli\Command\Ssh; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ssh-key:create-upload')] -class SshKeyCreateUploadCommand extends SshKeyCreateCommand { +#[RequireAuth] +#[AsCommand(name: 'ssh-key:create-upload', description: 'Create an SSH key on your local machine and upload it to the Cloud Platform')] +final class SshKeyCreateUploadCommand extends SshKeyCommandBase { protected function configure(): void { - $this->setDescription('Create an SSH key on your local machine and upload it to the Cloud Platform') + $this ->addOption('filename', NULL, InputOption::VALUE_REQUIRED, 'The filename of the SSH key') ->addOption('password', NULL, InputOption::VALUE_REQUIRED, 'The password for the SSH key') ->addOption('label', NULL, InputOption::VALUE_REQUIRED, 'The SSH key label to be used with the Cloud Platform') diff --git a/src/Command/Ssh/SshKeyDeleteCommand.php b/src/Command/Ssh/SshKeyDeleteCommand.php index 9dd917475..556a7dc94 100644 --- a/src/Command/Ssh/SshKeyDeleteCommand.php +++ b/src/Command/Ssh/SshKeyDeleteCommand.php @@ -4,19 +4,21 @@ namespace Acquia\Cli\Command\Ssh; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Helpers\SshCommandTrait; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ssh-key:delete')] -class SshKeyDeleteCommand extends SshKeyCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ssh-key:delete', description: 'Delete an SSH key')] +final class SshKeyDeleteCommand extends SshKeyCommandBase { use SshCommandTrait; protected function configure(): void { - $this->setDescription('Delete an SSH key') + $this ->addOption('cloud-key-uuid', 'uuid', InputOption::VALUE_REQUIRED); } diff --git a/src/Command/Ssh/SshKeyInfoCommand.php b/src/Command/Ssh/SshKeyInfoCommand.php index 5ee1325a4..06bf953f4 100644 --- a/src/Command/Ssh/SshKeyInfoCommand.php +++ b/src/Command/Ssh/SshKeyInfoCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ssh; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Exception\AcquiaCliException; use AcquiaCloudApi\Endpoints\SshKeys; use Symfony\Component\Console\Attribute\AsCommand; @@ -13,11 +14,12 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ssh-key:info')] -class SshKeyInfoCommand extends SshKeyCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ssh-key:info', description: 'Print information about an SSH key')] +final class SshKeyInfoCommand extends SshKeyCommandBase { protected function configure(): void { - $this->setDescription('Print information about an SSH key') + $this ->addOption('fingerprint', NULL, InputOption::VALUE_REQUIRED, 'sha256 fingerprint') ->addUsage('--fingerprint=pyarUa1mt2ln4fmrp7alWKpv1IPneqFwE+ErTC71IvY='); } diff --git a/src/Command/Ssh/SshKeyListCommand.php b/src/Command/Ssh/SshKeyListCommand.php index 3ae0f1225..cdb165aa6 100644 --- a/src/Command/Ssh/SshKeyListCommand.php +++ b/src/Command/Ssh/SshKeyListCommand.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command\Ssh; +use Acquia\Cli\Attribute\RequireAuth; use AcquiaCloudApi\Endpoints\SshKeys; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -11,12 +12,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ssh-key:list')] -class SshKeyListCommand extends SshKeyCommandBase { - - protected function configure(): void { - $this->setDescription('List your local and remote SSH keys'); - } +#[RequireAuth] +#[AsCommand(name: 'ssh-key:list', description: 'List your local and remote SSH keys')] +final class SshKeyListCommand extends SshKeyCommandBase { protected function execute(InputInterface $input, OutputInterface $output): int { $acquiaCloudClient = $this->cloudApiClientService->getClient(); diff --git a/src/Command/Ssh/SshKeyUploadCommand.php b/src/Command/Ssh/SshKeyUploadCommand.php index d51fcf3d7..cc55f90a7 100644 --- a/src/Command/Ssh/SshKeyUploadCommand.php +++ b/src/Command/Ssh/SshKeyUploadCommand.php @@ -4,17 +4,19 @@ namespace Acquia\Cli\Command\Ssh; +use Acquia\Cli\Attribute\RequireAuth; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -#[AsCommand(name: 'ssh-key:upload')] -class SshKeyUploadCommand extends SshKeyCommandBase { +#[RequireAuth] +#[AsCommand(name: 'ssh-key:upload', description: 'Upload a local SSH key to the Cloud Platform')] +final class SshKeyUploadCommand extends SshKeyCommandBase { protected function configure(): void { - $this->setDescription('Upload a local SSH key to the Cloud Platform') + $this ->addOption('filepath', NULL, InputOption::VALUE_REQUIRED, 'The filepath of the public SSH key to upload') ->addOption('label', NULL, InputOption::VALUE_REQUIRED, 'The SSH key label to be used with the Cloud Platform') ->addOption('no-wait', NULL, InputOption::VALUE_NONE, "Don't wait for the SSH key to be uploaded to the Cloud Platform"); diff --git a/src/Command/WizardCommandBase.php b/src/Command/WizardCommandBase.php index a582bbc4f..25891b497 100644 --- a/src/Command/WizardCommandBase.php +++ b/src/Command/WizardCommandBase.php @@ -4,6 +4,7 @@ namespace Acquia\Cli\Command; +use Acquia\Cli\Attribute\RequireAuth; use Acquia\Cli\Command\Ssh\SshKeyCommandBase; use Acquia\Cli\Exception\AcquiaCliException; use AcquiaCloudApi\Endpoints\SshKeys; @@ -16,7 +17,7 @@ abstract class WizardCommandBase extends SshKeyCommandBase { abstract protected function validateEnvironment(): void; protected function initialize(InputInterface $input, OutputInterface $output): void { - if ($this->commandRequiresAuthentication() && !$this->cloudApiClientService->isMachineAuthenticated()) { + if ((new \ReflectionClass(static::class))->getAttributes(RequireAuth::class) && !$this->cloudApiClientService->isMachineAuthenticated()) { $commandName = 'auth:login'; $command = $this->getApplication()->find($commandName); $arguments = ['command' => $commandName]; diff --git a/tests/phpunit/src/Application/KernelTest.php b/tests/phpunit/src/Application/KernelTest.php index 7bd3b929c..fc858a044 100644 --- a/tests/phpunit/src/Application/KernelTest.php +++ b/tests/phpunit/src/Application/KernelTest.php @@ -39,6 +39,7 @@ private function getStart(): string { completion Dump the shell completion script docs Open Acquia product documentation in a web browser help Display help for a command + list [self:list] List commands acsf acsf:list [acsf] List all Acquia Cloud Site Factory commands api @@ -99,7 +100,6 @@ private function getEnd(): string { remote:ssh [ssh] Use SSH to open a shell or run a command in a Cloud Platform environment self self:clear-caches [cc|cr] Clears local Acquia CLI caches - self:list [list] List commands self:telemetry:disable [telemetry:disable] Disable anonymous sharing of usage and performance data self:telemetry:enable [telemetry:enable] Enable anonymous sharing of usage and performance data self:telemetry:toggle [telemetry] Toggle anonymous sharing of usage and performance data