From eb95fea4d118ec548c08d93e31d7674ff6550363 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 11:43:30 +0000 Subject: [PATCH 01/11] Windows compatibility --- test/unit/ApplicationTest.php | 5 +++++ test/unit/StreamTest.php | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/unit/ApplicationTest.php b/test/unit/ApplicationTest.php index c8c707b..ab77d11 100644 --- a/test/unit/ApplicationTest.php +++ b/test/unit/ApplicationTest.php @@ -30,5 +30,10 @@ public function testSetStream() { $err = file_get_contents($errPath); self::assertContains("Application has no commands", $err); self::assertEmpty($out); + + $application = null; + unlink($inPath); + unlink($outPath); + unlink($errPath); } } \ No newline at end of file diff --git a/test/unit/StreamTest.php b/test/unit/StreamTest.php index 4e7d102..c20441c 100644 --- a/test/unit/StreamTest.php +++ b/test/unit/StreamTest.php @@ -37,13 +37,17 @@ public function testGetSetStream() { self::assertEquals($outPath, $out->getRealPath()); self::assertEquals($errPath, $err->getRealPath()); - chdir($tmp); + $stream = $in = $out = $err = null; foreach(scandir($tmp) as $file) { if($file[0] === ".") { continue; } - unlink($file); + $fullPath = implode(DIRECTORY_SEPARATOR, [ + $tmp, + $file, + ]); + unlink($fullPath); } rmdir($tmp); } From d55d979fbefc016466cc29e9712fb0f7aa66c790 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 11:43:47 +0000 Subject: [PATCH 02/11] Adjust error message --- src/Application.php | 2 +- test/unit/ApplicationTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Application.php b/src/Application.php index baf168e..81986ff 100644 --- a/src/Application.php +++ b/src/Application.php @@ -46,7 +46,7 @@ public function run():void { if(is_null($this->arguments)) { $this->stream->writeLine( - "Application has no commands", + "Application received no arguments", Stream::ERROR ); return; diff --git a/test/unit/ApplicationTest.php b/test/unit/ApplicationTest.php index ab77d11..e783ccf 100644 --- a/test/unit/ApplicationTest.php +++ b/test/unit/ApplicationTest.php @@ -28,7 +28,7 @@ public function testSetStream() { $out = file_get_contents($outPath); $err = file_get_contents($errPath); - self::assertContains("Application has no commands", $err); + self::assertContains("Application received no arguments", $err); self::assertEmpty($out); $application = null; From 2afe032300a2ff0098a5a693204599390fb11760 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 12:17:19 +0000 Subject: [PATCH 03/11] Test Application with invalid Command --- src/Application.php | 11 +++-- test/unit/ApplicationTest.php | 85 ++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/Application.php b/src/Application.php index 81986ff..21a4c2a 100644 --- a/src/Application.php +++ b/src/Application.php @@ -71,10 +71,13 @@ public function run():void { $exception->getMessage(), Stream::ERROR ); - $this->stream->writeLine( - $command->getUsage(), - Stream::ERROR - ); + + if(!is_null($command)) { + $this->stream->writeLine( + $command->getUsage(), + Stream::ERROR + ); + } } } diff --git a/test/unit/ApplicationTest.php b/test/unit/ApplicationTest.php index e783ccf..c8c85aa 100644 --- a/test/unit/ApplicationTest.php +++ b/test/unit/ApplicationTest.php @@ -2,38 +2,89 @@ namespace Gt\Cli\Test; use Gt\Cli\Application; +use Gt\Cli\Argument\ArgumentList; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; class ApplicationTest extends TestCase { - public function testSetStream() { - $tmp = implode(DIRECTORY_SEPARATOR, [ + protected $tmp; + protected $inPath; + protected $outPath; + protected $errPath; + + public function setUp() { + $this->tmp = implode(DIRECTORY_SEPARATOR, [ sys_get_temp_dir(), "phpgt", "cli", ]); - if(!is_dir($tmp)) { - mkdir($tmp, 0775, true); + if(!is_dir($this->tmp)) { + mkdir($this->tmp, 0775, true); + } + + $this->inPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, "in"]); + $this->outPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, "out"]); + $this->errPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, "err"]); + touch($this->inPath); + touch($this->outPath); + touch($this->errPath); + } + + public function tearDown() { + $fileList = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator( + $this->tmp, + RecursiveDirectoryIterator::SKIP_DOTS + ), + RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach($fileList as $fileInfo) { + $function = $fileInfo->isDir() + ? "rmdir" + : "unlink"; + + $function($fileInfo->getRealPath()); } - $inPath = implode(DIRECTORY_SEPARATOR, [$tmp, "in"]); - $outPath = implode(DIRECTORY_SEPARATOR, [$tmp, "out"]); - $errPath = implode(DIRECTORY_SEPARATOR, [$tmp, "err"]); - touch($inPath); - touch($outPath); - touch($errPath); + rmdir($this->tmp); + } + public function testSetStream() { $application = new Application("test-app"); - $application->setStream($inPath, $outPath, $errPath); + $application->setStream( + $this->inPath, + $this->outPath, + $this->errPath + ); $application->run(); - $out = file_get_contents($outPath); - $err = file_get_contents($errPath); + $out = file_get_contents($this->outPath); + $err = file_get_contents($this->errPath); self::assertContains("Application received no arguments", $err); self::assertEmpty($out); + } + + public function testCommandArgumentInvalid() { + /** @var ArgumentList|MockObject $arguments */ + $arguments = self::createMock(ArgumentList::class); + $arguments->method("getCommandName") + ->willReturn("test-command"); + + $application = new Application( + "test-app", + $arguments + ); + $application->setStream( + $this->inPath, + $this->outPath, + $this->errPath + ); + $application->run(); - $application = null; - unlink($inPath); - unlink($outPath); - unlink($errPath); + $err = file_get_contents($this->errPath); + self::assertContains("Invalid command: \"test-command\"", $err); } } \ No newline at end of file From 0e67afaf8f2bde119d9951e38c837b3940eb47cf Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 12:26:31 +0000 Subject: [PATCH 04/11] Refactor Application::run --- src/Application.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Application.php b/src/Application.php index 21a4c2a..2c62f71 100644 --- a/src/Application.php +++ b/src/Application.php @@ -60,7 +60,19 @@ public function run():void { $argumentValueList = $command->getArgumentValueList( $this->arguments ); + } + catch(CliException $exception) { + $this->stream->writeLine( + $exception->getMessage(), + Stream::ERROR + ); + } + if(is_null($command)) { + return; + } + + try { $command->checkArguments( $this->arguments ); @@ -68,16 +80,9 @@ public function run():void { } catch(CliException $exception) { $this->stream->writeLine( - $exception->getMessage(), + $command->getUsage(), Stream::ERROR ); - - if(!is_null($command)) { - $this->stream->writeLine( - $command->getUsage(), - Stream::ERROR - ); - } } } From ae16904c2003a662de7b4c32c1c4d123976dfea1 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 12:40:37 +0000 Subject: [PATCH 05/11] Test application's command with invalid arguments --- test/unit/ApplicationTest.php | 75 ++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/test/unit/ApplicationTest.php b/test/unit/ApplicationTest.php index c8c85aa..23a9aa9 100644 --- a/test/unit/ApplicationTest.php +++ b/test/unit/ApplicationTest.php @@ -3,6 +3,8 @@ use Gt\Cli\Application; use Gt\Cli\Argument\ArgumentList; +use Gt\Cli\Stream; +use Gt\Cli\Test\Helper\Command\TestCommand; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use RecursiveDirectoryIterator; @@ -24,9 +26,9 @@ public function setUp() { mkdir($this->tmp, 0775, true); } - $this->inPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, "in"]); - $this->outPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, "out"]); - $this->errPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, "err"]); + $this->inPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, Stream::IN]); + $this->outPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, Stream::OUT]); + $this->errPath = implode(DIRECTORY_SEPARATOR, [$this->tmp, STREAM::ERROR]); touch($this->inPath); touch($this->outPath); touch($this->errPath); @@ -61,10 +63,11 @@ public function testSetStream() { ); $application->run(); - $out = file_get_contents($this->outPath); - $err = file_get_contents($this->errPath); - self::assertContains("Application received no arguments", $err); - self::assertEmpty($out); + self::assertStreamContains( + "Application received no arguments", + Stream::ERROR + ); + self::assertStreamEmpty(Stream::OUT); } public function testCommandArgumentInvalid() { @@ -84,7 +87,61 @@ public function testCommandArgumentInvalid() { ); $application->run(); - $err = file_get_contents($this->errPath); - self::assertContains("Invalid command: \"test-command\"", $err); + self::assertStreamContains( + "Invalid command: \"test-command\"", + Stream::ERROR + ); + } + + public function testCommandArgumentsInvalid() { + /** @var MockObject|ArgumentList $arguments */ + $arguments = self::createMock(ArgumentList::class); + $arguments->method("getCommandName") + ->willReturn("invalid-test"); + + $application = new Application( + "test-app", + $arguments, + new TestCommand("invalid") + ); + $application->setStream( + $this->inPath, + $this->outPath, + $this->errPath + ); + $application->run(); + + self::assertStreamContains( + "Usage: invalid-test", + Stream::ERROR + ); + } + + protected function assertStreamContains( + string $message, + string $streamName + ):void { + $streamPath = $this->getStreamPathByName($streamName); + $streamContents = file_get_contents($streamPath); + self::assertContains( + $message, + $streamContents, + "Stream should contain message." + ); + } + + protected function assertStreamEmpty( + string $streamName + ):void { + $streamPath = $this->getStreamPathByName($streamName); + $streamContents = trim(file_get_contents($streamPath)); + self::assertEmpty($streamContents); + } + + protected function getStreamPathByName(string $name):string { + return implode(DIRECTORY_SEPARATOR, [ + $this->tmp, + $name, + ]); } } \ No newline at end of file From b647b883adef0c6716644901bfcba71ecd72b307 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 12:59:33 +0000 Subject: [PATCH 06/11] Test application's command with valid arguments --- test/unit/ApplicationTest.php | 67 ++++++++++++++++- test/unit/Command/CommandTest.php | 82 +-------------------- test/unit/Helper/ArgumentMockTestCase.php | 89 +++++++++++++++++++++++ test/unit/Helper/Command/TestCommand.php | 27 +++++++ 4 files changed, 184 insertions(+), 81 deletions(-) create mode 100644 test/unit/Helper/ArgumentMockTestCase.php diff --git a/test/unit/ApplicationTest.php b/test/unit/ApplicationTest.php index 23a9aa9..be48cc9 100644 --- a/test/unit/ApplicationTest.php +++ b/test/unit/ApplicationTest.php @@ -3,14 +3,17 @@ use Gt\Cli\Application; use Gt\Cli\Argument\ArgumentList; +use Gt\Cli\Argument\LongOptionArgument; +use Gt\Cli\Argument\NamedArgument; use Gt\Cli\Stream; +use Gt\Cli\Test\Helper\ArgumentMockTestCase; use Gt\Cli\Test\Helper\Command\TestCommand; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; -class ApplicationTest extends TestCase { +class ApplicationTest extends ArgumentMockTestCase { protected $tmp; protected $inPath; protected $outPath; @@ -117,6 +120,68 @@ public function testCommandArgumentsInvalid() { ); } + public function testCommandRun() { + $idArgument = self::createMock(NamedArgument::class); + $idArgument->method("getValue") + ->willReturn("abcde"); + $mustHaveValueArgument = self::createMock(LongOptionArgument::class); + $mustHaveValueArgument->method("getValue") + ->willReturn("1234"); + + $args = [ + $idArgument, + $mustHaveValueArgument, + ]; + $longArgs = [ + "abcde", + ["must-have-value" => "1234"], + ]; + + /** @var MockObject|ArgumentList $arguments */ + $arguments = self::createArgumentListMock( + $args, + $longArgs + ); + + $arguments->method("getCommandName") + ->willReturn("valid-test"); + + $application = new Application( + "test-app", + $arguments, + new TestCommand("valid") + ); + $application->setStream( + $this->inPath, + $this->outPath, + $this->errPath + ); + $application->run(); + + self::assertStreamEmpty(Stream::ERROR); + + self::assertStreamContains( + "Command ID: abcde", + Stream::OUT + ); + self::assertStreamContains( + "Command running successfully", + Stream::OUT + ); + self::assertStreamContains( + "No Option set", + Stream::OUT + ); + self::assertStreamContains( + "Must-have-value: 1234", + Stream::OUT + ); + self::assertStreamContains( + "No-value argument not set", + Stream::OUT + ); + } + protected function assertStreamContains( string $message, string $streamName diff --git a/test/unit/Command/CommandTest.php b/test/unit/Command/CommandTest.php index dff9f8a..91a8af6 100644 --- a/test/unit/Command/CommandTest.php +++ b/test/unit/Command/CommandTest.php @@ -15,6 +15,7 @@ use Gt\Cli\Parameter\MissingRequiredParameterValueException; use Gt\Cli\Parameter\Parameter; use Gt\Cli\Stream; +use Gt\Cli\Test\Helper\ArgumentMockTestCase; use Gt\Cli\Test\Helper\Command\AllParameterTypesCommand; use Gt\Cli\Test\Helper\Command\ComboRequiredOptionalParameterCommand; use Gt\Cli\Test\Helper\Command\MultipleRequiredParameterCommand; @@ -24,7 +25,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -class CommandTest extends TestCase { +class CommandTest extends ArgumentMockTestCase { public function testSetOutput() { /** @var Stream|MockObject $stream */ $stream = $this->createMock(Stream::class); @@ -300,83 +301,4 @@ public function testGetArgumentValueList() { self::assertEquals("Test name!", $argumentValueList->get("name")); self::assertEquals("test-scaffolding", $argumentValueList->get("framework")); } - - protected function createIteratorMock( - string $className, - array $items = [] - ):MockObject { - $mock = $this->createMock($className); - $iterator = new ArrayIterator($items); - - $mock->method("rewind") - ->willReturnCallback(function()use($iterator) { - $iterator->rewind(); - }); - $mock->method("current") - ->willReturnCallback(function()use($iterator) { - return $iterator->current(); - }); - $mock->method("key") - ->willReturnCallback(function()use($iterator) { - return $iterator->key(); - }); - $mock->method("next") - ->willReturnCallback(function()use($iterator) { - $iterator->next(); - }); - $mock->method("valid") - ->willReturnCallback(function()use($iterator) { - return $iterator->valid(); - }); - - return $mock; - } - - protected function createArgumentListMock( - array $items = [], - array $longArgs = [] - ):MockObject { - $argList = $this->createIteratorMock( - ArgumentList::class, - $items - ); - - $argList->method("contains") - ->willReturnCallback(function(Parameter $param)use($longArgs) { - $longOption = $param->getLongOption(); - foreach($longArgs as $a) { - if(is_array($a)) { - if(key($a) === $longOption) { - return true; - } - } - else { - if($a === $longOption) { - return true; - } - } - } - return false; - }); - - $argList->method("getValueForParameter") - ->willReturnCallback(function(Parameter $param)use($longArgs) { - $longOption = $param->getLongOption(); - foreach($longArgs as $a) { - if(!is_array($a)) { - continue; - } - - $key = key($a); - if($key !== $longOption) { - continue; - } - - return $a[$key]; - } - return null; - }); - - return $argList; - } } \ No newline at end of file diff --git a/test/unit/Helper/ArgumentMockTestCase.php b/test/unit/Helper/ArgumentMockTestCase.php new file mode 100644 index 0000000..6a44a28 --- /dev/null +++ b/test/unit/Helper/ArgumentMockTestCase.php @@ -0,0 +1,89 @@ +createMock($className); + $iterator = new ArrayIterator($items); + + $mock->method("rewind") + ->willReturnCallback(function()use($iterator) { + $iterator->rewind(); + }); + $mock->method("current") + ->willReturnCallback(function()use($iterator) { + return $iterator->current(); + }); + $mock->method("key") + ->willReturnCallback(function()use($iterator) { + return $iterator->key(); + }); + $mock->method("next") + ->willReturnCallback(function()use($iterator) { + $iterator->next(); + }); + $mock->method("valid") + ->willReturnCallback(function()use($iterator) { + return $iterator->valid(); + }); + + return $mock; + } + + protected function createArgumentListMock( + array $items = [], + array $longArgs = [] + ):MockObject { + $argList = $this->createIteratorMock( + ArgumentList::class, + $items + ); + + $argList->method("contains") + ->willReturnCallback(function(Parameter $param)use($longArgs) { + $longOption = $param->getLongOption(); + foreach($longArgs as $a) { + if(is_array($a)) { + if(key($a) === $longOption) { + return true; + } + } + else { + if($a === $longOption) { + return true; + } + } + } + return false; + }); + + $argList->method("getValueForParameter") + ->willReturnCallback(function(Parameter $param)use($longArgs) { + $longOption = $param->getLongOption(); + foreach($longArgs as $a) { + if(!is_array($a)) { + continue; + } + + $key = key($a); + if($key !== $longOption) { + continue; + } + + return $a[$key]; + } + return null; + }); + + return $argList; + } +} \ No newline at end of file diff --git a/test/unit/Helper/Command/TestCommand.php b/test/unit/Helper/Command/TestCommand.php index 3d9a1d0..fcf36f7 100644 --- a/test/unit/Helper/Command/TestCommand.php +++ b/test/unit/Helper/Command/TestCommand.php @@ -28,5 +28,32 @@ public function __construct(string $prefix = null) { } public function run(ArgumentValueList $arguments = null):void { + $this->writeLine("Command running successfully"); + + $this->writeLine( + "Command ID: " + . $arguments->get("id") + ); + + if($arguments->contains("option")) { + $this->writeLine( + "Option: " . $arguments->get("option") + ); + } + else { + $this->writeLine("No Option set"); + } + + $this->writeLine( + "Must-have-value: " + . $arguments->get("must-have-value") + ); + + if($arguments->contains("no-value")) { + $this->writeLine("No-value argument set"); + } + else { + $this->writeLine("No-value argument not set"); + } } } \ No newline at end of file From 1804277e3e59776d523b032ca17c4acb8e4a7127 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Fri, 18 Jan 2019 13:01:37 +0000 Subject: [PATCH 07/11] Tidy tests --- src/Command/Command.php | 1 - test/unit/Argument/ArgumentListTest.php | 1 - test/unit/Command/CommandTest.php | 5 ----- 3 files changed, 7 deletions(-) diff --git a/src/Command/Command.php b/src/Command/Command.php index 10c6e17..853347b 100644 --- a/src/Command/Command.php +++ b/src/Command/Command.php @@ -4,7 +4,6 @@ use Gt\Cli\Argument\Argument; use Gt\Cli\Argument\ArgumentList; use Gt\Cli\Argument\ArgumentValueList; -use Gt\Cli\Argument\CommandArgument; use Gt\Cli\Argument\NamedArgument; use Gt\Cli\Argument\NotEnoughArgumentsException; use Gt\Cli\Parameter\MissingRequiredParameterException; diff --git a/test/unit/Argument/ArgumentListTest.php b/test/unit/Argument/ArgumentListTest.php index 3065a21..e78b645 100644 --- a/test/unit/Argument/ArgumentListTest.php +++ b/test/unit/Argument/ArgumentListTest.php @@ -4,7 +4,6 @@ use Gt\Cli\Argument\Argument; use Gt\Cli\Argument\ArgumentList; use Gt\Cli\Parameter\Parameter; -use phpDocumentor\Reflection\DocBlock\Tags\Param; use PHPUnit\Framework\TestCase; class ArgumentListTest extends TestCase { diff --git a/test/unit/Command/CommandTest.php b/test/unit/Command/CommandTest.php index 91a8af6..a565e45 100644 --- a/test/unit/Command/CommandTest.php +++ b/test/unit/Command/CommandTest.php @@ -1,8 +1,6 @@ Date: Fri, 18 Jan 2019 13:07:13 +0000 Subject: [PATCH 08/11] Increase type safety in error class --- src/ErrorCode.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ErrorCode.php b/src/ErrorCode.php index 292fc26..53d1a7f 100644 --- a/src/ErrorCode.php +++ b/src/ErrorCode.php @@ -12,6 +12,7 @@ class ErrorCode { const DEFAULT_CODE = 1000; protected static $classList = [ + "NO_ERROR", NotEnoughArgumentsException::class, CommandException::class, InvalidCommandException::class, @@ -19,13 +20,9 @@ class ErrorCode { MissingRequiredParameterException::class, ]; - public static function get($exception):int { - if($exception instanceof Exception) { - $exception = get_class($exception); - } - + public static function get(string $exceptionClassName):int { return array_search( - $exception, + $exceptionClassName, self::$classList ) ?: self::DEFAULT_CODE; } From 8affee1e4bea5c6ae2bf72d30ca5ef64002b7925 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 22 Jan 2019 22:14:10 +0000 Subject: [PATCH 09/11] Tidy Help command output --- src/Application.php | 18 +++++------------- src/Command/Command.php | 6 +++++- src/Command/HelpCommand.php | 11 ++++++++++- src/ErrorCode.php | 9 ++++++--- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/Application.php b/src/Application.php index 2c62f71..baf168e 100644 --- a/src/Application.php +++ b/src/Application.php @@ -46,7 +46,7 @@ public function run():void { if(is_null($this->arguments)) { $this->stream->writeLine( - "Application received no arguments", + "Application has no commands", Stream::ERROR ); return; @@ -60,25 +60,17 @@ public function run():void { $argumentValueList = $command->getArgumentValueList( $this->arguments ); - } - catch(CliException $exception) { - $this->stream->writeLine( - $exception->getMessage(), - Stream::ERROR - ); - } - if(is_null($command)) { - return; - } - - try { $command->checkArguments( $this->arguments ); $command->run($argumentValueList); } catch(CliException $exception) { + $this->stream->writeLine( + $exception->getMessage(), + Stream::ERROR + ); $this->stream->writeLine( $command->getUsage(), Stream::ERROR diff --git a/src/Command/Command.php b/src/Command/Command.php index 853347b..5e8b46d 100644 --- a/src/Command/Command.php +++ b/src/Command/Command.php @@ -4,6 +4,7 @@ use Gt\Cli\Argument\Argument; use Gt\Cli\Argument\ArgumentList; use Gt\Cli\Argument\ArgumentValueList; +use Gt\Cli\Argument\CommandArgument; use Gt\Cli\Argument\NamedArgument; use Gt\Cli\Argument\NotEnoughArgumentsException; use Gt\Cli\Parameter\MissingRequiredParameterException; @@ -227,7 +228,10 @@ public function getArgumentValueList( $argumentValueList = new ArgumentValueList(); foreach($arguments as $argument) { - if($argument instanceof NamedArgument) { + if($argument instanceof CommandArgument) { + continue; + } + elseif($argument instanceof NamedArgument) { /** @var NamedParameter $parameter */ $parameter = $namedParameterList[ $namedParameterIndex diff --git a/src/Command/HelpCommand.php b/src/Command/HelpCommand.php index 39540ef..139f311 100644 --- a/src/Command/HelpCommand.php +++ b/src/Command/HelpCommand.php @@ -20,6 +20,7 @@ public function __construct( $this->applicationName = $applicationName; $this->applicationCommandList = $applicationCommandList; + $this->applicationCommandList []= $this; } public function run(ArgumentValueList $arguments = null): void { @@ -35,9 +36,17 @@ public function run(ArgumentValueList $arguments = null): void { $this->writeLine("Available commands:"); + $maxNameLength = 0; + foreach($this->applicationCommandList as $command) { + $nameLength = strlen($command->getName()); + if($nameLength > $maxNameLength) { + $maxNameLength = $nameLength; + } + } + foreach($this->applicationCommandList as $command) { $this->writeLine(" • " . - $command->getName() + str_pad($command->getName(), $maxNameLength, " ") . "\t" . $command->getDescription() ); diff --git a/src/ErrorCode.php b/src/ErrorCode.php index 53d1a7f..292fc26 100644 --- a/src/ErrorCode.php +++ b/src/ErrorCode.php @@ -12,7 +12,6 @@ class ErrorCode { const DEFAULT_CODE = 1000; protected static $classList = [ - "NO_ERROR", NotEnoughArgumentsException::class, CommandException::class, InvalidCommandException::class, @@ -20,9 +19,13 @@ class ErrorCode { MissingRequiredParameterException::class, ]; - public static function get(string $exceptionClassName):int { + public static function get($exception):int { + if($exception instanceof Exception) { + $exception = get_class($exception); + } + return array_search( - $exceptionClassName, + $exception, self::$classList ) ?: self::DEFAULT_CODE; } From 4325bd8ddcc71ef616051c11ab1e9ebb92058194 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 29 Jan 2019 17:46:28 +0000 Subject: [PATCH 10/11] Handle user data arguments, closes #16 --- src/Argument/Argument.php | 1 + src/Argument/ArgumentValueList.php | 1 + src/Command/Command.php | 17 +++++++++++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Argument/Argument.php b/src/Argument/Argument.php index 02ebd13..6ec88b7 100644 --- a/src/Argument/Argument.php +++ b/src/Argument/Argument.php @@ -2,6 +2,7 @@ namespace Gt\Cli\Argument; abstract class Argument { + const USER_DATA = "__user-data__"; protected $key; protected $value; diff --git a/src/Argument/ArgumentValueList.php b/src/Argument/ArgumentValueList.php index e1c578b..94bbfff 100644 --- a/src/Argument/ArgumentValueList.php +++ b/src/Argument/ArgumentValueList.php @@ -5,6 +5,7 @@ class ArgumentValueList { protected $valueMap = []; public function set(string $key, string $value = null):void { +// TODO: Issue #17 can convert existing values to arrays here. $this->valueMap[$key] = $value; } diff --git a/src/Command/Command.php b/src/Command/Command.php index 5e8b46d..1468362 100644 --- a/src/Command/Command.php +++ b/src/Command/Command.php @@ -237,10 +237,19 @@ public function getArgumentValueList( $namedParameterIndex ]; - $argumentValueList->set( - $parameter->getOptionName(), - $argument->getValue() - ); + if(is_null($parameter)) { + $argumentValueList->set( + Argument::USER_DATA, + $argument->getValue() + ); + } + else { + $argumentValueList->set( + $parameter->getOptionName(), + $argument->getValue() + ); + } + $namedParameterIndex++; } elseif($argument instanceof Argument) { From 9884732358a7e4b71fd573fe8c92743cc8f2626e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 4 Feb 2019 06:14:51 +0000 Subject: [PATCH 11/11] Bump phpunit/phpunit from 7.5.2 to 8.0.1 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 7.5.2 to 8.0.1. - [Release notes](https://github.com/sebastianbergmann/phpunit/releases) - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/master/ChangeLog-8.0.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/7.5.2...8.0.1) Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 88 +++++++++++++++++++++++++++------------------------ 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/composer.json b/composer.json index 20f213c..55db7e4 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ }, "require-dev": { - "phpunit/phpunit": "7.*" + "phpunit/phpunit": "8.*" }, "license": "MIT", diff --git a/composer.lock b/composer.lock index 1bd5ad3..95dbe42 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d1f204477b29b76cd651ce6285c018e4", + "content-hash": "3ce2cb44f3fa77c339ecff0a2c1fae6b", "packages": [], "packages-dev": [ { @@ -428,40 +428,40 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.1.4", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + "reference": "4832739a02c418397e404da6c3e4fe680b7a4de7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4832739a02c418397e404da6c3e4fe680b7a4de7", + "reference": "4832739a02c418397e404da6c3e4fe680b7a4de7", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", + "php": "^7.2", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", + "phpunit/php-token-stream": "^3.0.1", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", + "sebastian/environment": "^4.1", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.0" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-xdebug": "^2.6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -487,7 +487,7 @@ "testing", "xunit" ], - "time": "2018-10-31T16:06:48+00:00" + "time": "2019-02-01T07:29:14+00:00" }, { "name": "phpunit/php-file-iterator", @@ -680,16 +680,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.5.2", + "version": "8.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7c89093bd00f7d5ddf0ab81dee04f801416b4944" + "reference": "753a192050133fc649234de34d1993d87785b134" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7c89093bd00f7d5ddf0ab81dee04f801416b4944", - "reference": "7c89093bd00f7d5ddf0ab81dee04f801416b4944", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/753a192050133fc649234de34d1993d87785b134", + "reference": "753a192050133fc649234de34d1993d87785b134", "shasum": "" }, "require": { @@ -699,27 +699,25 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", + "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.7", "phar-io/manifest": "^1.0.2", "phar-io/version": "^2.0", - "php": "^7.1", + "php": "^7.2", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-code-coverage": "^7.0", "phpunit/php-file-iterator": "^2.0.1", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^2.0", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", + "sebastian/environment": "^4.1", "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", + "sebastian/global-state": "^3.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^2.0", "sebastian/version": "^2.0.1" }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" - }, "require-dev": { "ext-pdo": "*" }, @@ -734,7 +732,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.5-dev" + "dev-master": "8.0-dev" } }, "autoload": { @@ -760,7 +758,7 @@ "testing", "xunit" ], - "time": "2019-01-15T08:19:08+00:00" + "time": "2019-02-03T17:34:56+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -929,28 +927,31 @@ }, { "name": "sebastian/environment", - "version": "4.0.1", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f" + "reference": "6fda8ce1974b62b14935adc02a9ed38252eca656" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/febd209a219cea7b56ad799b30ebbea34b71eb8f", - "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6fda8ce1974b62b14935adc02a9ed38252eca656", + "reference": "6fda8ce1974b62b14935adc02a9ed38252eca656", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^7.4" + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -975,7 +976,7 @@ "environment", "hhvm" ], - "time": "2018-11-25T09:31:21+00:00" + "time": "2019-02-01T05:27:49+00:00" }, { "name": "sebastian/exporter", @@ -1046,23 +1047,26 @@ }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", + "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-uopz": "*" @@ -1070,7 +1074,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1093,7 +1097,7 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2019-02-01T05:30:01+00:00" }, { "name": "sebastian/object-enumerator", @@ -1370,7 +1374,7 @@ }, { "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "email": "backendtea@gmail.com" } ], "description": "Symfony polyfill for ctype functions",