From 4e036a5ce88553af6ff55d717ed71a00c43705d8 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 25 Jul 2022 11:41:56 -0700 Subject: [PATCH] CLI improvements for non-interactive shells Resolves #11650 --- CHANGELOG-WIP.md | 1 + src/console/controllers/DbController.php | 12 ++++++------ src/console/controllers/ElementsController.php | 2 +- src/console/controllers/GraphqlController.php | 2 +- src/console/controllers/IndexAssetsController.php | 2 +- src/console/controllers/MigrateController.php | 4 ++-- src/console/controllers/SetupController.php | 4 ++-- src/console/controllers/TestsController.php | 4 ++-- src/console/controllers/UsersController.php | 15 ++++++++++----- .../utils/AsciiFilenamesController.php | 2 +- 10 files changed, 27 insertions(+), 21 deletions(-) diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md index 95faf40fd9c..a6d0cbcc270 100644 --- a/CHANGELOG-WIP.md +++ b/CHANGELOG-WIP.md @@ -22,6 +22,7 @@ - Improved Image Editor accessibility. ([#11496](https://github.com/craftcms/cms/pull/11496)) - The “Keep me signed in” checkbox label on the control panel’s login page now includes the remembered session duration, e.g. “Keep me signed in for 2 weeks”. ([#11594](https://github.com/craftcms/cms/discussions/11594)) - Dashboard widgets no longer show a confirmation dialog when deleted. Their delete notifications include an “Undo” button instead. ([#11573](https://github.com/craftcms/cms/discussions/11573)) +- Improved the behavior of some console commands for non-interactive shells. ([#11650](https://github.com/craftcms/cms/issues/11650)) - `config/general.php` and `config/db.php` can now return `craft\config\GeneralConfig`/`DbConfig` objects, which can be defined using new fluent setter methods. ([#11591](https://github.com/craftcms/cms/pull/11591), [#11656](https://github.com/craftcms/cms/pull/11656)) - The `|duration` Twig filter can now be used with an integer representing a number of seconds, and its `showSeconds` argument is no longer required. Seconds will be output if the duration is less than one minute by default. - The `|length` Twig filter now checks if the variable is a query, and if so, returns its count. ([#11625](https://github.com/craftcms/cms/discussions/11625)) diff --git a/src/console/controllers/DbController.php b/src/console/controllers/DbController.php index 0c76b8b30e2..7487b00525c 100644 --- a/src/console/controllers/DbController.php +++ b/src/console/controllers/DbController.php @@ -82,7 +82,7 @@ public function actionDropAllTables(): int return ExitCode::OK; } - if (!$this->confirm('Are you sure you want to drop all tables from the database?')) { + if ($this->interactive && !$this->confirm('Are you sure you want to drop all tables from the database?')) { $this->stdout('Aborted.' . PHP_EOL, Console::FG_YELLOW); return ExitCode::OK; } @@ -195,14 +195,14 @@ public function actionBackup(?string $path = null): int foreach ($checkPaths as $checkPath) { if (is_file($checkPath)) { if (!$this->overwrite) { - if (!$this->confirm("$checkPath already exists. Overwrite?")) { - if ($this->interactive) { - $this->stdout('Aborting' . PHP_EOL); - return ExitCode::OK; - } + if (!$this->interactive) { $this->stderr("$checkPath already exists. Retry with the --overwrite flag to overwrite it." . PHP_EOL, Console::FG_RED); return ExitCode::UNSPECIFIED_ERROR; } + if (!$this->confirm("$checkPath already exists. Overwrite?")) { + $this->stdout('Aborting' . PHP_EOL); + return ExitCode::OK; + } } unlink($checkPath); } diff --git a/src/console/controllers/ElementsController.php b/src/console/controllers/ElementsController.php index 4317e46af29..d8682ce254c 100644 --- a/src/console/controllers/ElementsController.php +++ b/src/console/controllers/ElementsController.php @@ -68,7 +68,7 @@ public function actionDelete(int $id): int return ExitCode::UNSPECIFIED_ERROR; } - if (!$this->confirm(sprintf('Are you sure you want to %s “%s”?', $this->hard ? 'hard-delete' : 'delete', $title))) { + if ($this->interactive && !$this->confirm(sprintf('Are you sure you want to %s “%s”?', $this->hard ? 'hard-delete' : 'delete', $title))) { return ExitCode::OK; } diff --git a/src/console/controllers/GraphqlController.php b/src/console/controllers/GraphqlController.php index df794a90789..010d663542c 100644 --- a/src/console/controllers/GraphqlController.php +++ b/src/console/controllers/GraphqlController.php @@ -185,7 +185,7 @@ public function actionCreateToken(string $schemaUid): int $this->stderr("Invalid expiry date: $this->expiry" . PHP_EOL, Console::FG_RED); return ExitCode::UNSPECIFIED_ERROR; } - } elseif ($this->confirm('Set an expiry date?')) { + } elseif ($this->interactive && $this->confirm('Set an expiry date?')) { $expiryDate = $this->prompt('Expiry date:', [ 'required' => true, 'validator' => function(string $input): bool { diff --git a/src/console/controllers/IndexAssetsController.php b/src/console/controllers/IndexAssetsController.php index 41dbba8e077..d7dfd0f62f2 100644 --- a/src/console/controllers/IndexAssetsController.php +++ b/src/console/controllers/IndexAssetsController.php @@ -237,7 +237,7 @@ private function _indexAssets(array $volumes, string $path = '', int $startAt = $remainingMissingFiles = $missingFiles; - if ($maybes && $this->confirm('Fix asset locations?')) { + if ($maybes && $this->interactive && $this->confirm('Fix asset locations?')) { foreach ($missingFiles as $assetId => $filePath) { unset($remainingMissingFiles[$assetId]); $filename = basename($filePath); diff --git a/src/console/controllers/MigrateController.php b/src/console/controllers/MigrateController.php index 1de56991874..902d23b06c9 100644 --- a/src/console/controllers/MigrateController.php +++ b/src/console/controllers/MigrateController.php @@ -255,7 +255,7 @@ public function actionCreate($name): int $file = $this->migrationPath . DIRECTORY_SEPARATOR . $name . '.php'; - if ($this->confirm("Create new migration '$file'?", true)) { + if (!$this->interactive || $this->confirm("Create new migration '$file'?", true)) { $templateFile = Craft::getAlias($this->templateFile); if ($templateFile === false) { @@ -338,7 +338,7 @@ public function actionAll(): int $total += $n; } - if (!$this->confirm('Apply the above ' . ($total === 1 ? 'migration' : 'migrations') . '?')) { + if ($this->interactive && !$this->confirm('Apply the above ' . ($total === 1 ? 'migration' : 'migrations') . '?')) { return ExitCode::OK; } diff --git a/src/console/controllers/SetupController.php b/src/console/controllers/SetupController.php index 1ea33789dce..853cd5ad5b4 100644 --- a/src/console/controllers/SetupController.php +++ b/src/console/controllers/SetupController.php @@ -129,7 +129,7 @@ public function actionIndex(): int return ExitCode::OK; } - if (!$this->confirm(PHP_EOL . 'Install Craft now?', true)) { + if ($this->interactive && !$this->confirm(PHP_EOL . 'Install Craft now?', true)) { $this->stdout("You can install Craft from a browser once you've set up a web server, or by running this command:" . PHP_EOL, Console::FG_YELLOW); $this->_outputCommand('install'); return ExitCode::OK; @@ -558,7 +558,7 @@ private function _setEnvVar(string $name, mixed $value): bool $path = $configService->getDotEnvPath(); if (!file_exists($path)) { - if ($this->confirm(PHP_EOL . "A .env file doesn't exist at $path. Would you like to create one?", true)) { + if (!$this->interactive || $this->confirm(PHP_EOL . "A .env file doesn't exist at $path. Would you like to create one?", true)) { try { FileHelper::writeToFile($path, ''); } catch (Throwable $e) { diff --git a/src/console/controllers/TestsController.php b/src/console/controllers/TestsController.php index 1697d6fc0df..3a8cd732aa5 100644 --- a/src/console/controllers/TestsController.php +++ b/src/console/controllers/TestsController.php @@ -72,7 +72,7 @@ public function actionSetup(?string $dst = null): int } $this->stdout(PHP_EOL); - if (!$this->confirm('Are you sure you want to continue?')) { + if ($this->interactive && !$this->confirm('Are you sure you want to continue?')) { $this->stdout('Aborting.' . PHP_EOL); return ExitCode::UNSPECIFIED_ERROR; } @@ -85,7 +85,7 @@ public function actionSetup(?string $dst = null): int $this->stdout("- $file" . PHP_EOL); } $this->stdout(PHP_EOL); - if (!$this->confirm('Continue?', true)) { + if ($this->interactive && !$this->confirm('Continue?', true)) { $this->stdout('Aborting.' . PHP_EOL); return ExitCode::UNSPECIFIED_ERROR; } diff --git a/src/console/controllers/UsersController.php b/src/console/controllers/UsersController.php index 6fd4eb91997..b494fac0455 100644 --- a/src/console/controllers/UsersController.php +++ b/src/console/controllers/UsersController.php @@ -197,19 +197,24 @@ public function actionCreate(): int ]); } - $user->admin = $this->admin ?? $this->confirm('Make this user an admin?', false); + $user->admin = $this->admin ?? ($this->interactive && $this->confirm('Make this user an admin?')); if ($this->password) { $user->newPassword = $this->password; } elseif ($this->interactive) { - if ($this->confirm('Set a password for this user?', false)) { + if ($this->confirm('Set a password for this user?')) { $user->newPassword = $this->passwordPrompt([ 'validator' => $this->createAttributeValidator($user, 'newPassword'), ]); } } - $user->active = $this->activate ?? $this->confirm('Activate the account?', $user->newPassword !== null); + if ($this->activate !== null) { + $user->active = $this->activate; + } else { + $defaultActivate = $user->newPassword !== null; + $user->active = $this->interactive ? $this->confirm('Activate the account?', $defaultActivate) : $defaultActivate; + } $this->stdout('Saving the user ... '); @@ -314,7 +319,7 @@ public function actionDelete(string $user): int return ExitCode::USAGE; } - if (!$this->inheritor && $this->confirm('Transfer this user’s content to an existing user?', true)) { + if (!$this->inheritor && $this->interactive && $this->confirm('Transfer this user’s content to an existing user?', true)) { $this->inheritor = $this->prompt('Enter the email or username of the user to inherit the content:', [ 'required' => true, ]); @@ -328,7 +333,7 @@ public function actionDelete(string $user): int return ExitCode::UNSPECIFIED_ERROR; } - if (!$this->confirm("Delete user “{$user->username}” and transfer their content to user “{$inheritor->username}”?")) { + if ($this->interactive && !$this->confirm("Delete user “{$user->username}” and transfer their content to user “{$inheritor->username}”?")) { $this->stdout('Aborting.' . PHP_EOL); return ExitCode::OK; } diff --git a/src/console/controllers/utils/AsciiFilenamesController.php b/src/console/controllers/utils/AsciiFilenamesController.php index 8b369f24e9a..abc5004cc4e 100644 --- a/src/console/controllers/utils/AsciiFilenamesController.php +++ b/src/console/controllers/utils/AsciiFilenamesController.php @@ -74,7 +74,7 @@ public function actionIndex(): int $this->stdout(PHP_EOL); - if (!$this->confirm('Ready to rename these filenames as ASCII?', true)) { + if ($this->interactive && !$this->confirm('Ready to rename these filenames as ASCII?', true)) { return ExitCode::OK; }