diff --git a/lib/PhpParser/BuilderFactory.php b/lib/PhpParser/BuilderFactory.php index 1975572..c515c9e 100644 --- a/lib/PhpParser/BuilderFactory.php +++ b/lib/PhpParser/BuilderFactory.php @@ -3,6 +3,9 @@ namespace PhpParser; use PhpParser\Builder; +use PhpParser\Node\Expr; +use PhpParser\Node\Expr\BinaryOp\Concat; +use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Use_; /** @@ -120,14 +123,34 @@ class BuilderFactory /** * Creates node a for a literal value. * - * @param Node\Expr|bool|null|int|float|string|array $value $value + * @param Expr|bool|null|int|float|string|array $value $value * - * @return Node\Expr + * @return Expr */ public function val($value) { return BuilderHelpers::normalizeValue($value); } + /** + * Creates nested Concat nodes from a list of expressions. + * + * @param Expr|string ...$exprs Expressions or literal strings + * + * @return Concat + */ + public function concat(...$exprs) { + $numExprs = count($exprs); + if ($numExprs < 2) { + throw new \LogicException('Expected at least two expressions'); + } + + $lastConcat = $this->normalizeStringExpr($exprs[0]); + for ($i = 1; $i < $numExprs; $i++) { + $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); + } + return $lastConcat; + } + public function __call($name, array $args) { if (method_exists($this, '_' . $name)) { return $this->{'_' . $name}(...$args); @@ -135,4 +158,16 @@ class BuilderFactory throw new \LogicException(sprintf('Method "%s" does not exist', $name)); } + + private function normalizeStringExpr($expr) { + if ($expr instanceof Expr) { + return $expr; + } + + if (is_string($expr)) { + return new String_($expr); + } + + throw new \LogicException('Expected string or Expr'); + } } diff --git a/test/PhpParser/BuilderFactoryTest.php b/test/PhpParser/BuilderFactoryTest.php index e0ab32e..f4c74ea 100644 --- a/test/PhpParser/BuilderFactoryTest.php +++ b/test/PhpParser/BuilderFactoryTest.php @@ -3,6 +3,7 @@ namespace PhpParser; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\BinaryOp\Concat; use PhpParser\Node\Scalar\String_; class BuilderFactoryTest extends \PHPUnit_Framework_TestCase @@ -45,6 +46,42 @@ class BuilderFactoryTest extends \PHPUnit_Framework_TestCase ); } + public function testConcat() { + $factory = new BuilderFactory(); + $varA = new Expr\Variable('a'); + $varB = new Expr\Variable('b'); + $varC = new Expr\Variable('c'); + + $this->assertEquals( + new Concat($varA, $varB), + $factory->concat($varA, $varB) + ); + $this->assertEquals( + new Concat(new Concat($varA, $varB), $varC), + $factory->concat($varA, $varB, $varC) + ); + $this->assertEquals( + new Concat(new Concat(new String_("a"), $varB), new String_("c")), + $factory->concat("a", $varB, "c") + ); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Expected at least two expressions + */ + public function testConcatOneError() { + (new BuilderFactory())->concat("a"); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Expected string or Expr + */ + public function testConcatInvalidExpr() { + (new BuilderFactory())->concat("a", 42); + } + public function testIntegration() { $factory = new BuilderFactory; $node = $factory->namespace('Name\Space')