From 3cebbdad2e00029ba0c2cb8d4841c9e2af6b3948 Mon Sep 17 00:00:00 2001 From: rhertogh Date: Fri, 9 Jun 2023 18:36:21 +0200 Subject: [PATCH] Fix #19853: Added support for default value for `\yii\helpers\Console::select()` --- framework/CHANGELOG.md | 1 + framework/UPGRADE.md | 11 +++ framework/console/Controller.php | 11 ++- framework/helpers/BaseConsole.php | 10 ++- tests/framework/helpers/ConsoleTest.php | 97 ++++++++++++++----------- 5 files changed, 83 insertions(+), 47 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index de4721cf51..9f859c5e5c 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 Change Log - Bug #18859: Fix `yii\web\Controller::bindInjectedParams()` to not throw error when argument of `ReflectionUnionType` type is passed (bizley) - Enh #19841: Allow jQuery 3.7 to be installed (wouter90) +- Enh #19853: Added support for default value for `\yii\helpers\Console::select()` (rhertogh) 2.0.48.1 May 24, 2023 diff --git a/framework/UPGRADE.md b/framework/UPGRADE.md index 898f77c694..7d2ca03eb9 100644 --- a/framework/UPGRADE.md +++ b/framework/UPGRADE.md @@ -52,6 +52,17 @@ version B between A and C, you need to follow the instructions for both A and B. +Upgrade from Yii 2.0.48 +----------------------- + +* Since Yii 2.0.49 the `yii\console\Controller::select()` function supports a default value and respects + the `yii\console\Controller::$interactive` setting. Before the user was always prompted to select an option + regardless of the `$interactive` setting. Now the `$default` value is automatically returned when `$interactive` is + `false`. +* The function signature for `yii\console\Controller::select()` and `yii\helpers\BaseConsole::select()` have changed. + They now have an additional `$default = null` parameter. In case those methods are overwritten you will need to + update your child classes accordingly. + Upgrade from Yii 2.0.46 ----------------------- diff --git a/framework/console/Controller.php b/framework/console/Controller.php index 8762d338b5..579b597783 100644 --- a/framework/console/Controller.php +++ b/framework/console/Controller.php @@ -400,12 +400,19 @@ class Controller extends \yii\base\Controller * * @param string $prompt the prompt message * @param array $options Key-value array of options to choose from + * @param string|null $default value to use when the user doesn't provide an option. + * If the default is `null`, the user is required to select an option. * * @return string An option character the user chose + * @since 2.0.49 Added the $default argument */ - public function select($prompt, $options = []) + public function select($prompt, $options = [], $default = null) { - return Console::select($prompt, $options); + if ($this->interactive) { + return Console::select($prompt, $options, $default); + } + + return $default; } /** diff --git a/framework/helpers/BaseConsole.php b/framework/helpers/BaseConsole.php index abb838c9c4..febeed313b 100644 --- a/framework/helpers/BaseConsole.php +++ b/framework/helpers/BaseConsole.php @@ -948,13 +948,17 @@ class BaseConsole * @param string $prompt the prompt message * @param array $options Key-value array of options to choose from. Key is what is inputed and used, value is * what's displayed to end user by help command. + * @param string|null $default value to use when the user doesn't provide an option. + * If the default is `null`, the user is required to select an option. * * @return string An option character the user chose + * @since 2.0.49 Added the $default argument */ - public static function select($prompt, $options = []) + public static function select($prompt, $options = [], $default = null) { top: - static::stdout("$prompt [" . implode(',', array_keys($options)) . ',?]: '); + static::stdout("$prompt (" . implode(',', array_keys($options)) . ',?)' + . ($default !== null ? '[' . $default . ']' : '') . ': '); $input = static::stdin(); if ($input === '?') { foreach ($options as $key => $value) { @@ -962,6 +966,8 @@ class BaseConsole } static::output(' ? - Show help'); goto top; + } elseif ($default !== null && $input === '') { + return $default; } elseif (!array_key_exists($input, $options)) { goto top; } diff --git a/tests/framework/helpers/ConsoleTest.php b/tests/framework/helpers/ConsoleTest.php index b729e26691..cbd1b322ee 100644 --- a/tests/framework/helpers/ConsoleTest.php +++ b/tests/framework/helpers/ConsoleTest.php @@ -216,27 +216,6 @@ class ConsoleTest extends TestCase $expectedHtml = "Error message. Here are some chars: < >\nError message. Here are even more chars: \"\""; $this->assertEqualsWithoutLE($expectedHtml, Console::errorSummary($model, $options)); } -} - -/** - * @property string name - * @property array types - * @property string description - */ -class TestConsoleModel extends DynamicModel -{ - public function rules() - { - return [ - ['name', 'required'], - ['name', 'string', 'max' => 100] - ]; - } - - public function init() - { - $this->defineAttribute('name'); - } /** * @covers \yii\helpers\BaseConsole::input() @@ -390,16 +369,16 @@ class TestConsoleModel extends DynamicModel $this->truncateStreams(); foreach ([ - 'y' => true, - 'Y' => true, - 'yes' => true, - 'YeS' => true, - 'n' => false, - 'N' => false, - 'no' => false, - 'NO' => false, - 'WHAT?!' . PHP_EOL . 'yes' => true, - ] as $currInput => $currAssertion) { + 'y' => true, + 'Y' => true, + 'yes' => true, + 'YeS' => true, + 'n' => false, + 'N' => false, + 'no' => false, + 'NO' => false, + 'WHAT?!' . PHP_EOL . 'yes' => true, + ] as $currInput => $currAssertion) { $this->sendInput($currInput); $result = ConsoleStub::confirm('Are you sure?'); $this->assertEquals($currAssertion, $result, $currInput); @@ -420,31 +399,63 @@ class TestConsoleModel extends DynamicModel $this->sendInput('c'); $result = ConsoleStub::select('Usual behavior', $options); - $this->assertEquals('Usual behavior [c,d,m,?]: ', $this->readOutput()); + $this->assertEquals('Usual behavior (c,d,m,?): ', $this->readOutput()); $this->assertEquals('c', $result); $this->truncateStreams(); $this->sendInput('x', 'd'); $result = ConsoleStub::select('Wrong character', $options); - $this->assertEquals('Wrong character [c,d,m,?]: Wrong character [c,d,m,?]: ', $this->readOutput()); + $this->assertEquals('Wrong character (c,d,m,?): Wrong character (c,d,m,?): ', $this->readOutput()); $this->assertEquals('d', $result); $this->truncateStreams(); $this->sendInput('?', 'm'); $result = ConsoleStub::select('Using help', $options); $this->assertEquals( - 'Using help [c,d,m,?]: ' - . ' c - cat' - . PHP_EOL - . ' d - dog' - . PHP_EOL - . ' m - mouse' - . PHP_EOL - . ' ? - Show help' - . PHP_EOL - . 'Using help [c,d,m,?]: ', + 'Using help (c,d,m,?): ' + . ' c - cat' + . PHP_EOL + . ' d - dog' + . PHP_EOL + . ' m - mouse' + . PHP_EOL + . ' ? - Show help' + . PHP_EOL + . 'Using help (c,d,m,?): ', $this->readOutput() ); $this->truncateStreams(); + + $this->sendInput(''); + $result = ConsoleStub::select('Use Default', $options, 'm'); + $this->assertEquals('m', $result); + $this->truncateStreams(); + + $this->sendInput('', 'd'); + $result = ConsoleStub::select('Empty without Default', $options); + $this->assertEquals('Empty without Default (c,d,m,?): Empty without Default (c,d,m,?): ', $this->readOutput()); + $this->assertEquals('d', $result); + $this->truncateStreams(); + } +} + +/** + * @property string name + * @property array types + * @property string description + */ +class TestConsoleModel extends DynamicModel +{ + public function rules() + { + return [ + ['name', 'required'], + ['name', 'string', 'max' => 100] + ]; + } + + public function init() + { + $this->defineAttribute('name'); } }