This repository has been archived by the owner on Jan 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request zendframework/zendframework#7091 from Lansoweb/dev…
…elop Added Checkbox Console Prompt and its tests
- Loading branch information
166 parents
c26f58a
+
dfbe5c2
+
bcf0eb7
+
df35d8a
+
c0d4707
+
fb9dce0
+
c45b896
+
739e942
+
29a4517
+
3179585
+
ae205d0
+
6d3ab5a
+
5b7a64f
+
7591112
+
7610b9a
+
f91c471
+
acef74d
+
d753e94
+
7a829bf
+
3b93376
+
6c2eca4
+
48bc01e
+
3c88cd5
+
fbfc750
+
441b9de
+
b57e2b9
+
2beef92
+
3ae4add
+
994832b
+
6db3cde
+
e0f83ee
+
712223d
+
3b4ec35
+
e53a267
+
51bf3c7
+
10a1e95
+
30ee303
+
96417b9
+
50ea13f
+
24d1c0c
+
b09295e
+
13758aa
+
99316f8
+
40b8ac3
+
e284e0b
+
8ff51b4
+
4b5ea1e
+
5b24371
+
ed932b6
+
357852d
+
262e5d6
+
9057a3f
+
0e1e846
+
5d11876
+
0ae0984
+
6ff135c
+
0b45aba
+
1778b0c
+
a574713
+
ba3f132
+
56365a6
+
019f89a
+
b09b3ba
+
2af32d0
+
cb39fc7
+
3f8a6fd
+
8999753
+
a7cd86b
+
da1c469
+
5371cdb
+
fd9f625
+
99d3fcd
+
1e3ed17
+
a360459
+
1a1e9aa
+
4c8955c
+
94f2feb
+
5b450ef
+
e64e5b0
+
e9d19a6
+
a5a9b6e
+
5e59c3a
+
a47f2db
+
3cf915a
+
a2a5c91
+
1cd3439
+
ef9c643
+
298a619
+
001ae99
+
c37ab8e
+
017f6f1
+
0711f77
+
38af804
+
23120b4
+
5f96f53
+
a257169
+
8085bc4
+
3110cd4
+
f270d41
+
9536f09
+
4ec1292
+
adcdd78
+
e80fff6
+
99fc5ce
+
1d23e94
+
fa167cb
+
a93e92f
+
13a2df8
+
06689fb
+
2d601eb
+
72a3295
+
a59f42c
+
0f4489d
+
b3f7029
+
3c492ce
+
259bcdc
+
a811ae5
+
f66f985
+
173e949
+
b93077e
+
f11a10d
+
5ac4be0
+
cb31aff
+
d34bdbb
+
725b978
+
27b423e
+
624ac5e
+
a3340ac
+
80ab2e3
+
3429053
+
998a6d7
+
8b9ab71
+
d4dffb0
+
5456435
+
97180fa
+
126be7f
+
c16eb72
+
8ccb096
+
50481b9
+
411738a
+
50b5c0b
+
0721376
+
ca3399f
+
5abf474
+
7783b57
+
a53deb5
+
c8885be
+
1adf3e3
+
5a45e41
+
3370b44
+
b4caa32
+
2a7fc79
+
755e064
+
fde42e0
+
fb9bce8
+
3ff447c
+
7cbed25
+
61aff3c
+
a27b9cd
+
7bfc680
+
3a02933
+
ca6dcba
+
d776971
+
b515ef9
+
c7e321d
+
0a3000f
commit 17effe7
Showing
3 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
<?php | ||
/** | ||
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) | ||
* @license http://framework.zend.com/license/new-bsd New BSD License | ||
*/ | ||
namespace Zend\Console\Prompt; | ||
|
||
use Zend\Console\Exception; | ||
use Zend\Stdlib\ArrayUtils; | ||
|
||
final class Checkbox extends AbstractPrompt | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
private $promptText; | ||
|
||
/** | ||
* @var bool | ||
*/ | ||
private $ignoreCase; | ||
|
||
/** | ||
* @var array|Transversable | ||
*/ | ||
private $options; | ||
|
||
/** | ||
* Checked options | ||
* @var array | ||
*/ | ||
private $checkedOptions = array(); | ||
|
||
/** | ||
* If the response should be echoed to the console or not | ||
* @var bool | ||
*/ | ||
private $echo; | ||
|
||
/** | ||
* Ask the user to select any number of pre-defined options | ||
* | ||
* @param string $promptText The prompt text to display in console | ||
* @param array|Transversable $options Allowed options | ||
* @param bool $echo True to display selected option? | ||
*/ | ||
public function __construct($promptText = 'Please select one option (Enter to finish) ', $options = array(), $ignoreCase = true, $echo = false) | ||
{ | ||
$this->promptText = (string) $promptText; | ||
|
||
$this->setOptions($options); | ||
|
||
$this->echo = (bool) $echo; | ||
|
||
$this->ignoreCase = (bool) $ignoreCase; | ||
} | ||
|
||
/** | ||
* Show a list of options and prompt the user to select any number of them. | ||
* | ||
* @return array Checked options | ||
*/ | ||
public function show() | ||
{ | ||
$this->checkedOptions = array(); | ||
$mask = $this->prepareMask(); | ||
|
||
do { | ||
$this->showAvailableOptions(); | ||
|
||
$response = $this->readOption($mask); | ||
|
||
if ($this->echo) { | ||
$this->showResponse($response); | ||
} | ||
|
||
$this->checkOrUncheckOption($response); | ||
} while ($response != "\r" && $response != "\n"); | ||
|
||
$this->lastResponse = $this->checkedOptions; | ||
|
||
return $this->checkedOptions; | ||
} | ||
|
||
/** | ||
* Shows the selected option to the screen | ||
* @param string $response | ||
*/ | ||
private function showResponse($response) | ||
{ | ||
$console = $this->getConsole(); | ||
if (isset($this->options[$response])) { | ||
$console->writeLine($this->options[$response]); | ||
} else { | ||
$console->writeLine(); | ||
} | ||
} | ||
|
||
/** | ||
* Check or uncheck an option | ||
* | ||
* @param string $response | ||
*/ | ||
private function checkOrUncheckOption($response) | ||
{ | ||
if ($response != "\r" && $response != "\n" && isset($this->options[$response])) { | ||
$pos = array_search($this->options[$response], $this->checkedOptions); | ||
if ($pos === false) { | ||
$this->checkedOptions[] = $this->options[$response]; | ||
} else { | ||
array_splice($this->checkedOptions, $pos, 1); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Generates a mask to to be used by the readChar method. | ||
* | ||
* @return string | ||
*/ | ||
private function prepareMask() | ||
{ | ||
$mask = implode("", array_keys($this->options)) . "\r\n"; | ||
|
||
/** | ||
* Normalize the mask if case is irrelevant | ||
*/ | ||
if (!$this->ignoreCase) { | ||
return $mask; | ||
} | ||
|
||
$mask = implode("", array_unique(str_split(strtolower($mask) . strtoupper($mask)))); | ||
|
||
return $mask; | ||
} | ||
|
||
/** | ||
* Reads a char from console. | ||
* | ||
* @param string $mask | ||
* @return string | ||
*/ | ||
private function readOption($mask) | ||
{ | ||
/** | ||
* Read char from console | ||
*/ | ||
|
||
return $this->getConsole()->readChar($mask); | ||
} | ||
|
||
/** | ||
* Shows the available options with checked and unchecked states | ||
*/ | ||
private function showAvailableOptions() | ||
{ | ||
$console = $this->getConsole(); | ||
$console->writeLine($this->promptText); | ||
foreach ($this->options as $k => $v) { | ||
$console->writeLine(' ' . $k . ') ' . (in_array($v, $this->checkedOptions) ? '[X] ' : '[ ] ') . $v); | ||
} | ||
} | ||
|
||
/** | ||
* Set allowed options | ||
* | ||
* @param array|\Traversable $options | ||
* @throws Exception\InvalidArgumentException | ||
*/ | ||
private function setOptions($options) | ||
{ | ||
$options = ArrayUtils::iteratorToArray($options); | ||
|
||
if (empty($options)) { | ||
throw new Exception\InvalidArgumentException('Please, specify at least one option'); | ||
} | ||
|
||
$this->options = $options; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?php | ||
/** | ||
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) | ||
* @license http://framework.zend.com/license/new-bsd New BSD License | ||
*/ | ||
|
||
namespace ZendTest\Console\Prompt; | ||
|
||
use Zend\Console\Prompt\Checkbox; | ||
use ZendTest\Console\TestAssets\ConsoleAdapter; | ||
|
||
/** | ||
* @group Zend_Console | ||
* @covers \Zend\Console\Prompt\Checkbox | ||
*/ | ||
class CheckboxTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @var ConsoleAdapter | ||
*/ | ||
protected $adapter; | ||
|
||
public function setUp() | ||
{ | ||
$this->adapter = new ConsoleAdapter(false); | ||
$this->adapter->stream = fopen('php://memory', 'w+'); | ||
} | ||
|
||
public function tearDown() | ||
{ | ||
fclose($this->adapter->stream); | ||
} | ||
|
||
public function testCanCheckOneOption() | ||
{ | ||
fwrite($this->adapter->stream, "0"); | ||
fwrite($this->adapter->stream, "\n"); | ||
rewind($this->adapter->stream); | ||
|
||
$checkbox = new Checkbox('Check an option :', array('foo', 'bar')); | ||
$checkbox->setConsole($this->adapter); | ||
ob_start(); | ||
$response = $checkbox->show(); | ||
$text = ob_get_clean(); | ||
$this->assertSame(1, substr_count($text, '0) [X] foo')); | ||
$this->assertSame(1, substr_count($text, '0) [ ] foo')); | ||
$this->assertSame(2, substr_count($text, '1) [ ] bar')); | ||
$this->assertEquals(['0' => 'foo'], $response); | ||
} | ||
|
||
public function testCanUncheckOneOption() | ||
{ | ||
fwrite($this->adapter->stream, "0"); | ||
fwrite($this->adapter->stream, "0"); | ||
fwrite($this->adapter->stream, "\n"); | ||
rewind($this->adapter->stream); | ||
|
||
$checkbox = new Checkbox('Check an option :', array('foo', 'bar')); | ||
$checkbox->setConsole($this->adapter); | ||
ob_start(); | ||
$response = $checkbox->show(); | ||
$text = ob_get_clean(); | ||
$this->assertSame(1, substr_count($text, '0) [X] foo')); | ||
$this->assertSame(2, substr_count($text, '0) [ ] foo')); | ||
$this->assertSame(3, substr_count($text, '1) [ ] bar')); | ||
$this->assertEquals([], $response); | ||
} | ||
|
||
public function testCanCheckTwoOption() | ||
{ | ||
fwrite($this->adapter->stream, "0"); | ||
fwrite($this->adapter->stream, "1"); | ||
fwrite($this->adapter->stream, "\n"); | ||
rewind($this->adapter->stream); | ||
|
||
$checkbox = new Checkbox('Check an option :', array('foo', 'bar')); | ||
$checkbox->setConsole($this->adapter); | ||
ob_start(); | ||
$response = $checkbox->show(); | ||
$text = ob_get_clean(); | ||
$this->assertSame(2, substr_count($text, '0) [X] foo')); | ||
$this->assertSame(1, substr_count($text, '1) [X] bar')); | ||
$this->assertSame(1, substr_count($text, '0) [ ] foo')); | ||
$this->assertSame(2, substr_count($text, '1) [ ] bar')); | ||
$this->assertEquals(['0' => 'foo', '1' => 'bar'], $response); | ||
} | ||
|
||
public function testCanCheckOptionWithCustomIndex() | ||
{ | ||
fwrite($this->adapter->stream, "2"); | ||
fwrite($this->adapter->stream, "\n"); | ||
rewind($this->adapter->stream); | ||
|
||
$checkbox = new Checkbox('Check an option :', array('2' => 'foo', '6' => 'bar')); | ||
$checkbox->setConsole($this->adapter); | ||
ob_start(); | ||
$response = $checkbox->show(); | ||
$text = ob_get_clean(); | ||
$this->assertSame(1, substr_count($text, '2) [X] foo')); | ||
$this->assertSame(1, substr_count($text, '2) [ ] foo')); | ||
$this->assertSame(2, substr_count($text, '6) [ ] bar')); | ||
$this->assertEquals(['0' => 'foo'], $response); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters