diff --git a/composer.json b/composer.json index 8fe41c7..861d967 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "license": "MIT", "authors": [ { - "name": "Chris Ben", + "name": "Christian Rodriguez Benthake", "email": "git@cben.co" } ], diff --git a/src/ShellBuilder.php b/src/ShellBuilder.php index 378275d..5a345ec 100644 --- a/src/ShellBuilder.php +++ b/src/ShellBuilder.php @@ -17,6 +17,8 @@ final class ShellBuilder implements ShellInterface, \JsonSerializable { + use ShellConditional; + /** @var array */ private $commandList = []; /** @var int */ @@ -296,7 +298,7 @@ public function createCommandSubstition(): self public function hasCommands(): bool { - return empty($this->commandList) && empty($this->variables); + return empty($this->commandList) === false || empty($this->variables) === false; } /** @@ -366,7 +368,7 @@ public function __toString(): string } if ($this->groupType === GroupType::SAMESHELL_GROUP) { return sprintf( - '%s%s;%s', + '%s %s;%s', ControlOperator::CURLY_BLOCK_DEFINITON_OPEN, $result, ControlOperator::CURLY_BLOCK_DEFINITON_CLOSE diff --git a/src/ShellCommand.php b/src/ShellCommand.php index 32dddbc..3e8751d 100644 --- a/src/ShellCommand.php +++ b/src/ShellCommand.php @@ -18,6 +18,8 @@ */ final class ShellCommand implements ShellInterface { + use ShellConditional; + /** * @var ShellWord * @psalm-readonly diff --git a/src/ShellConditional.php b/src/ShellConditional.php new file mode 100644 index 0000000..64e580c --- /dev/null +++ b/src/ShellConditional.php @@ -0,0 +1,28 @@ +if($callOnThis($this) === true, $callback, $alternativeCallback); + } +} diff --git a/tests/ShellBuilderTest.php b/tests/ShellBuilderTest.php index 267a9bd..489ff8f 100644 --- a/tests/ShellBuilderTest.php +++ b/tests/ShellBuilderTest.php @@ -17,7 +17,7 @@ final class ShellBuilderTest extends TestCase { public function testBuilderConcept(): void { - $result = 'a && b | c || d |& f && (g && h) || {i || j;}'; + $result = 'a && b | c || d |& f && (g && h) || { i || j;}'; $builder = new ShellBuilder(); $a = $builder->createCommand('a'); $b = $builder->createCommand('b'); @@ -46,7 +46,7 @@ public function testBuilderConcept(): void public function testBuilderConceptWithShortcut(): void { - $result = 'a && b | c || d |& f && (g && h) || {i || j;}'; + $result = 'a && b | c || d |& f && (g && h) || { i || j;}'; $builder = new ShellBuilder(); $builder ->add('a') @@ -160,7 +160,7 @@ public function testShellBuilderGroupSameShell(): void ->add( $builder->createCommand('echo')->addArgument('hello') )->and('cat')); - $this->assertEquals("{echo 'hello' && cat;}", (string)$builder); + $this->assertEquals("{ echo 'hello' && cat;}", (string)$builder); } public function testSimpleSshCommand(): void @@ -683,7 +683,7 @@ public function testCoprocessWithShellGroupAndRedirections(): void ->addToBuilder() ->redirectDescriptor('', true, null, 3); $this->assertEquals( - '{coproc tee {tee logfile;} >&3 ;} 3>&1', + '{ coproc tee { tee logfile;} >&3 ;} 3>&1', (string)ShellBuilder::new()->add($builder)->redirectDescriptor('', true, 3, 1) ); } @@ -700,11 +700,85 @@ public function testNamedCoprocessWithShellGroupAndRedirections(): void ->addToBuilder()) ->redirectDescriptor('', true, null, 3); $this->assertEquals( - '{coproc mycoproc {awk \'{print "foo" $0;fflush()}\';} >&3 ;} 3>&1', + '{ coproc mycoproc { awk \'{print "foo" $0;fflush()}\';} >&3 ;} 3>&1', (string)ShellBuilder::new()->add($builder)->redirectDescriptor('', true, 3, 1) ); } + public function testCondiditionalArguments(): void + { + // if false + $builder = ShellBuilder::new() + ->if(false, static function (ShellBuilder $builder) { + return $builder->add('echo'); + }) + ->ifThis(static function (ShellBuilder $builder) { + return $builder->hasCommands() === false; + }, static function (ShellBuilder $builder) { + return $builder->add('print'); + }); + static::assertEquals('print', (string)$builder); + + // if true + $builder = ShellBuilder::new() + ->if(true, static function (ShellBuilder $builder) { + return $builder->add('echo'); + }) + ->ifThis(static function (ShellBuilder $builder) { + return $builder->hasCommands() === false; + }, static function (ShellBuilder $builder) { + return $builder->add('print'); + }); + static::assertEquals('echo', (string)$builder); + } + + public function testComplexCondiditionalArguments(): void + { + $builder = ShellBuilder::new() + ->if( + false, + static function (ShellBuilder $builder) { + return $builder->add('echo'); + }, + static function (ShellBuilder $builder) { + return $builder->add('awk'); + } + ) + ->ifThis(static function (ShellBuilder $builder) { + return $builder->hasCommands() === false; + }, static function (ShellBuilder $builder) { + return $builder->add('print'); + }, static function (ShellBuilder $builder) { + return $builder->and('print'); + }); + static::assertEquals('awk && print', (string)$builder); + } + + public function testComplexCondiditionalArgumentsWithWrongArguments(): void + { + self::expectException(\ErrorException::class); + ShellBuilder::new() + ->ifThis(static function (ShellBuilder $builder) { + return 'world'; + }, static function (ShellBuilder $builder) { + return $builder->add('print'); + }, static function (ShellBuilder $builder) { + return 'bla'; + }); + } + + public function testCondiditionalArgumentsWithWrongArguments(): void + { + self::expectException(\ErrorException::class); + ShellBuilder::new() + ->if( + true, + static function (ShellBuilder $builder) { + return 'hello world'; + } + ); + } + public function testSimpleAsyncShellBuilder(): void { $this->assertEquals( @@ -789,18 +863,18 @@ public function testCommandVariableWithConditionalAndCommand(): void public function testShellBuilderIsEmpty(): void { $builder = ShellBuilder::new(); - $this->assertTrue($builder->hasCommands()); + $this->assertFalse($builder->hasCommands()); } public function testShellBuilderIsNotEmpty(): void { $builder = ShellBuilder::new(); $builder->addVariable('a', 'b'); - $this->assertFalse($builder->hasCommands()); - $builder->removeVariable('a'); $this->assertTrue($builder->hasCommands()); - $builder->add('echo'); + $builder->removeVariable('a'); $this->assertFalse($builder->hasCommands()); + $builder->add('echo'); + $this->assertTrue($builder->hasCommands()); } public function testAddVariableWithoutSemicolon(): void diff --git a/tests/ShellCommandTest.php b/tests/ShellCommandTest.php index e19d9ee..06287e7 100644 --- a/tests/ShellCommandTest.php +++ b/tests/ShellCommandTest.php @@ -6,6 +6,7 @@ use PHPSu\ShellCommandBuilder\Definition\GroupType; use PHPSu\ShellCommandBuilder\Exception\ShellBuilderException; +use PHPSu\ShellCommandBuilder\ShellBuilder; use PHPSu\ShellCommandBuilder\ShellCommand; use PHPUnit\Framework\TestCase; @@ -171,6 +172,18 @@ public function testShellCommandWithCommandSubstitutionToArray(): void ], $command['arguments']); } + public function testConditionalArguments() + { + $command = ShellBuilder::command('test') + ->if(1 + 1 === 3, static function (ShellCommand $command) { + return $command->addOption('f', '1 + 1 = 3'); + }) + ->if(1 + 1 === 2, static function (ShellCommand $command) { + return $command->addOption('t', '1 + 1 = 2'); + }); + static::assertEquals((string)$command, 'test --t \'1 + 1 = 2\''); + } + public function testUnEscapedOption(): void { $command = (new ShellCommand('ls'))->addOption('color', 'true', false, true);