diff --git a/src/Builder.php b/src/Builder.php index ae66a72..428e4b8 100644 --- a/src/Builder.php +++ b/src/Builder.php @@ -7,19 +7,22 @@ */ namespace Madkom\NginxConfigurator; +use Countable; +use Madkom\Collection\CustomTypedCollection; use Madkom\NginxConfigurator\Config\Server; use Madkom\NginxConfigurator\Config\Upstream; use Madkom\NginxConfigurator\Node\Directive; use Madkom\NginxConfigurator\Node\Node; use Madkom\NginxConfigurator\Node\Param; use Madkom\NginxConfigurator\Node\RootNode; +use Traversable; /** * Class Builder * @package Madkom\NginxConfigurator * @author Michał Brzuchalski */ -class Builder +class Builder implements Countable { /** * @var RootNode Holds configuration root node @@ -30,30 +33,12 @@ class Builder * Builder constructor. */ public function __construct() - { - $this->clear(); - } - - public function clear() { $this->rootNode = new RootNode(); } /** - * @param int $port - * @return Server - */ - public function addServerNode(int $port) : Server - { - $listenIPv4 = new Directive('listen', [new Param($port)]); - $listenIPv6 = new Directive('listen', [new Param("[::]:{$port}"), new Param('default'), new Param('ipv6only=on')]); - $httpNode = new Server([$listenIPv4, $listenIPv6]); - $this->rootNode->append($httpNode); - - return $httpNode; - } - - /** + * Append child node * @param Node $node * @return Node */ @@ -64,6 +49,46 @@ class Builder return $node; } + /** + * Remove child node + * @param Node $node + * @return bool + */ + public function remove(Node $node) : bool + { + return $this->rootNode->remove($node); + } + + /** + * Search for specified nodes + * @param callable $checker + * @return CustomTypedCollection + */ + public function search(callable $checker) : CustomTypedCollection + { + return $this->rootNode->filter($checker); + } + + /** + * Count elements of an object + * @link http://php.net/manual/en/countable.count.php + * @return int The custom count as an integer. + */ + public function count() + { + return count($this->rootNode); + } + + /** + * Retrieve an external iterator + * @link http://php.net/manual/en/iteratoraggregate.getiterator.php + * @return Traversable An instance of an object implementing Iterator or + */ + public function getIterator() + { + return $this->rootNode->getIterator(); + } + /** * @return string */ diff --git a/src/Factory.php b/src/Factory.php new file mode 100644 index 0000000..2f55bc2 --- /dev/null +++ b/src/Factory.php @@ -0,0 +1,45 @@ + + */ +class Factory +{ + /** + * Creates Server node + * @param int $port + * @return Server + */ + public function createServer(int $port = 80) : Server + { + $listenIPv4 = new Directive('listen', [new Param($port)]); + $listenIPv6 = new Directive('listen', [new Param("[::]:{$port}"), new Param('default'), new Param('ipv6only=on')]); + + return new Server([$listenIPv4, $listenIPv6]); + } + + /** + * Creates Location node + * @param string $location + * @param string|null $match + * @return Location + */ + public function createLocation(string $location, string $match = null) : Location + { + return new Location(new Param($location), is_null($match) ? null : new Param($match)); + } +} diff --git a/tests/spec/BuilderSpec.php b/tests/spec/BuilderSpec.php new file mode 100644 index 0000000..43ed9a1 --- /dev/null +++ b/tests/spec/BuilderSpec.php @@ -0,0 +1,38 @@ + + * @mixin Builder + */ +class BuilderSpec extends ObjectBehavior +{ + function it_is_initializable() + { + $this->shouldHaveType(Builder::class); + } + + function it_can_build_with_Server_node(Server $server) + { + $server->__toString()->willReturn("server { +}"); + $this->append($server); + $this->dump()->shouldBeString(); + } + + function it_can_build_with_Upstream_node(Upstream $upstream) + { + $upstream->__toString()->willReturn("upstream name { +}"); + $this->append($upstream); + $this->dump()->shouldBeString(); + } +} diff --git a/tests/spec/FactorySpec.php b/tests/spec/FactorySpec.php new file mode 100644 index 0000000..a384e74 --- /dev/null +++ b/tests/spec/FactorySpec.php @@ -0,0 +1,32 @@ + + * @mixin Factory + */ +class FactorySpec extends ObjectBehavior +{ + function it_is_initializable() + { + $this->shouldHaveType(Factory::class); + } + + function it_can_create_Server_node() + { + $this->createServer(80)->shouldReturnAnInstanceOf(Server::class); + } + + function it_can_create_Location_node() + { + $this->createLocation('/test', '~')->shouldReturnAnInstanceOf(Location::class); + } +} diff --git a/tests/spec/ParserSpec.php b/tests/spec/ParserSpec.php index 9aa5049..9a4ca37 100644 --- a/tests/spec/ParserSpec.php +++ b/tests/spec/ParserSpec.php @@ -3,11 +3,15 @@ namespace spec\Madkom\NginxConfigurator; use Ferno\Loco\ParseFailureException; +use Madkom\NginxConfigurator\Config\Http; use Madkom\NginxConfigurator\Config\Location; use Madkom\NginxConfigurator\Config\Server; +use Madkom\NginxConfigurator\Config\Upstream; use Madkom\NginxConfigurator\Node\Context; use Madkom\NginxConfigurator\Node\Directive; +use Madkom\NginxConfigurator\Node\Literal; use Madkom\NginxConfigurator\Node\Node; +use Madkom\NginxConfigurator\Node\Param; use Madkom\NginxConfigurator\Node\RootNode; use Madkom\NginxConfigurator\Parser; use PhpSpec\ObjectBehavior; @@ -25,7 +29,7 @@ class ParserSpec extends ObjectBehavior { function it_is_initializable() { - $this->shouldHaveType('Madkom\NginxConfigurator\Parser'); + $this->shouldHaveType(Parser::class); } /** @@ -184,4 +188,67 @@ EOF } } } + + function it_can_parse_Upstream_and_Http_contexts() + { + $root = $this->parse(<<shouldReturnAnInstanceOf(RootNode::class); + + $contexts = $root->search(function (Node $node) { + return $node; + })->getWrappedObject(); + /** @var Context $context */ + foreach ($contexts as $index => $context) { + switch ($index) { + case 0: + Assert::assertInstanceOf(Http::class, $context); + break; + case 1: + Assert::assertInstanceOf(Upstream::class, $context); + /** @var Directive $directive */ + foreach ($context as $index => $directive) { + switch ($index) { + case 0: + Assert::assertEquals('internal', $directive->getName()); + break; + } + } + break; + } + } + } + + /** + * @throws ParseFailureException + */ + function it_can_parse_Literal_directive() + { + /** @var RootNode $root */ + $root = $this->parse(<<shouldReturnAnInstanceOf(RootNode::class); + + $directives = $root->search(function (Node $node) { + return $node; + })->getWrappedObject(); + /** @var Directive $directive */ + foreach ($directives as $directive) { + break; + } + Assert::assertEquals($directive->getName(), 'internal'); + Assert::assertInstanceOf(Traversable::class, $directive->getParams()); + /** @var Param $param */ + foreach ($directive->getParams() as $param) { + Assert::assertInstanceOf(Literal::class, $param); + } + } }