From 0e8ee80fd4b3372cb983ff0eeed02a961bbf003a Mon Sep 17 00:00:00 2001 From: jigius Date: Mon, 23 Aug 2021 11:04:33 +0700 Subject: [PATCH 1/2] add the supporting of Twig v3 --- composer.json | 10 ++-- lib/TwigStack/Extension/StackExtension.php | 25 ++++++---- lib/TwigStack/Node/StackBodyNode.php | 27 ++++++---- lib/TwigStack/Node/StackPopNode.php | 25 +++++++--- lib/TwigStack/Node/StackPushNode.php | 34 +++++++++---- .../NodeVisitor/StackNodeVisitor.php | 45 +++++++++-------- lib/TwigStack/Stack.php | 9 ++-- .../TokenParser/StackPopTokenParser.php | 36 ++++++++----- .../TokenParser/StackPushTokenParser.php | 50 ++++++++++++------- test/TwigStack/Tests/Fixtures/stack.test | 1 - test/TwigStack/Tests/IntegrationTest.php | 9 ++-- 11 files changed, 170 insertions(+), 101 deletions(-) diff --git a/composer.json b/composer.json index ef6204a..b727d27 100644 --- a/composer.json +++ b/composer.json @@ -11,15 +11,15 @@ } ], "require": { - "php": ">=5.3.3", - "twig/twig": "1.*" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*" + "php": ">=7.2.5", + "twig/twig": "^3" }, "autoload": { "psr-0" : { "TwigStack" : "lib/" } + }, + "require-dev": { + "phpunit/phpunit": "^9.5" } } diff --git a/lib/TwigStack/Extension/StackExtension.php b/lib/TwigStack/Extension/StackExtension.php index 0394da0..1500026 100644 --- a/lib/TwigStack/Extension/StackExtension.php +++ b/lib/TwigStack/Extension/StackExtension.php @@ -10,10 +10,12 @@ namespace TwigStack\Extension; +use Twig\NodeVisitor\NodeVisitorInterface; use TwigStack\NodeVisitor\StackNodeVisitor; use TwigStack\Stack; use TwigStack\TokenParser\StackPopTokenParser; use TwigStack\TokenParser\StackPushTokenParser; +use Twig; /** * The Twig extension, which should be added to the Twig environment to enable TwigStack @@ -21,7 +23,7 @@ * @package TwigStack\Extension * @author Arno Geurts */ -class StackExtension extends \Twig_Extension +class StackExtension extends Twig\Extension\AbstractExtension { /** * @var array|Stack[] @@ -34,8 +36,9 @@ class StackExtension extends \Twig_Extension * * @param string $stackName * @param string $content + * @return void */ - public function pushStack($stackName, $content) + public function pushStack(string $stackName, string $content): void { if (!array_key_exists($stackName, $this->stacks)) { $this->stacks[$stackName] = new Stack(); @@ -49,12 +52,12 @@ public function pushStack($stackName, $content) * @param string $output * @return string */ - public function render($output) + public function render(string $output): string { $stacks = $this->stacks; // try to find the following string in the output // stack_pop_[stashName]([seperator]) - $regex = '/stack\_pop\_([\w]*)\(([^\)]*)\)/'; + $regex = '/stack_pop_([\w]*)\(([^)]*)\)/'; $callback = function($matches) use ($stacks) { // if the requested stack does not exists, replace it with an empty string if (!array_key_exists($matches[1], $stacks)) { @@ -76,23 +79,23 @@ public function render($output) * * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances */ - public function getTokenParsers() + public function getTokenParsers(): array { return array( - new StackPushTokenParser(), - new StackPopTokenParser() + new StackPushTokenParser($this), + new StackPopTokenParser($this) ); } /** * Returns the node visitor instances to add to the existing list. * - * @return \Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances + * @return NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances */ - public function getNodeVisitors() + public function getNodeVisitors(): array { return array( - new StackNodeVisitor() + new StackNodeVisitor($this) ); } @@ -101,7 +104,7 @@ public function getNodeVisitors() * * @return string The extension name */ - public function getName() + public function getName(): string { return 'stack'; } diff --git a/lib/TwigStack/Node/StackBodyNode.php b/lib/TwigStack/Node/StackBodyNode.php index 145b045..c56ba15 100644 --- a/lib/TwigStack/Node/StackBodyNode.php +++ b/lib/TwigStack/Node/StackBodyNode.php @@ -10,28 +10,38 @@ namespace TwigStack\Node; +use Twig\Node\Node; +use Twig; + /** * Class StackBodyNode * @package TwigStack\Node */ -class StackBodyNode extends \Twig_Node +class StackBodyNode extends Node { /** - * Consturct the stack body with the original body + * @var Twig\Extension\ExtensionInterface + */ + private $ext; + + /** + * Construct the stack body with the original body * - * @param \Twig_Node $body + * @param Twig\Extension\ExtensionInterface $ext + * @param Node $body */ - public function __construct(\Twig_Node $body) + public function __construct(Twig\Extension\ExtensionInterface $ext, Node $body) { parent::__construct(array('body' => $body)); + $this->ext = $ext; } /** * Compiles the node to PHP. * - * @param \Twig_Compiler A Twig_Compiler instance + * @param Twig\Compiler $compiler A Twig_Compiler instance */ - public function compile(\Twig_Compiler $compiler) + public function compile(Twig\Compiler $compiler) { $compiler ->write("ob_start();\n") @@ -45,7 +55,6 @@ public function compile(\Twig_Compiler $compiler) ->write("throw \$e;\n") ->outdent() ->write("}\n\n") - ->write("echo \$this->env->getExtension('stack')->render(ob_get_clean());\n\n") - ; + ->write("echo \$this->env->getExtension(" . get_class($this->ext) . "::class)->render(ob_get_clean());\n\n"); } -} \ No newline at end of file +} diff --git a/lib/TwigStack/Node/StackPopNode.php b/lib/TwigStack/Node/StackPopNode.php index 3de3866..4c20e55 100644 --- a/lib/TwigStack/Node/StackPopNode.php +++ b/lib/TwigStack/Node/StackPopNode.php @@ -10,28 +10,41 @@ namespace TwigStack\Node; +use Twig; + /** * Class StackPopNode * @package TwigStack\Node */ -class StackPopNode extends \Twig_Node +class StackPopNode extends Twig\Node\Node { /** + * @var Twig\Extension\ExtensionInterface + */ + private $ext; + + /** + * @param Twig\Extension\ExtensionInterface $ext, * @param string $name - * @param \Twig_Node $separator + * @param Twig\Node\Node $separator * @param int $lineno */ - public function __construct($name, \Twig_Node $separator, $lineno = 0) - { + public function __construct( + Twig\Extension\ExtensionInterface $ext, + string $name, + Twig\Node\Node $separator, + int $lineno = 0 + ) { parent::__construct(array('separator' => $separator), array('name' => $name), $lineno); + $this->ext = $ext; } /** * Compiles the node to PHP. * - * @param \Twig_Compiler A Twig_Compiler instance + * @param Twig\Compiler $compiler A Twig_Compiler instance */ - public function compile(\Twig_Compiler $compiler) + public function compile(Twig\Compiler $compiler) { $compiler ->write(sprintf("echo 'stack_pop_%s(' . ", $this->getAttribute('name'))) diff --git a/lib/TwigStack/Node/StackPushNode.php b/lib/TwigStack/Node/StackPushNode.php index ff2fb47..ac4a482 100644 --- a/lib/TwigStack/Node/StackPushNode.php +++ b/lib/TwigStack/Node/StackPushNode.php @@ -10,31 +10,46 @@ namespace TwigStack\Node; +use Twig; +use TwigStack\Extension\StackExtension; + /** * Class StackPushNode * @package TwigStack\Node */ -class StackPushNode extends \Twig_Node +class StackPushNode extends Twig\Node\Node { + /** + * @var Twig\Extension\ExtensionInterface + */ + private $ext; + /** * Construct the stack body with the original body * + * @param Twig\Extension\ExtensionInterface $ext * @param string $name - * @param \Twig_Node $body + * @param Twig\Node\Node $body * @param int $lineno - * @param string $tag + * @param string|null $tag */ - public function __construct($name, \Twig_Node $body, $lineno = 0, $tag = null) - { + public function __construct( + Twig\Extension\ExtensionInterface $ext, + string $name, + Twig\Node\Node $body, + int $lineno = 0, + string $tag = null + ) { parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag); + $this->ext = $ext; } /** * Compiles the node to PHP. * - * @param \Twig_Compiler A Twig_Compiler instance + * @param Twig\Compiler $compiler A Twig\Compiler instance */ - public function compile(\Twig_Compiler $compiler) + public function compile(Twig\Compiler $compiler) { $compiler ->write("ob_start();\n") @@ -49,7 +64,6 @@ public function compile(\Twig_Compiler $compiler) ->outdent() ->write("}\n\n") ->write("\$result = ob_get_clean();\n") - ->write(sprintf("\$this->env->getExtension('stack')->pushStack('%s', \$result);\n\n", $this->getAttribute('name'))); - ; + ->write(sprintf("\$this->env->getExtension(" . get_class($this->ext) . "::class)->pushStack('%s', \$result);\n\n", $this->getAttribute('name'))); } -} \ No newline at end of file +} diff --git a/lib/TwigStack/NodeVisitor/StackNodeVisitor.php b/lib/TwigStack/NodeVisitor/StackNodeVisitor.php index 9592c5b..df2292c 100644 --- a/lib/TwigStack/NodeVisitor/StackNodeVisitor.php +++ b/lib/TwigStack/NodeVisitor/StackNodeVisitor.php @@ -10,39 +10,42 @@ namespace TwigStack\NodeVisitor; +use Twig\Environment; +use Twig\Node\Node; use TwigStack\Node\StackBodyNode; +use Twig; /** * Class StackNodeVisitor * @package TwigStack\NodeVisitor */ -class StackNodeVisitor implements \Twig_NodeVisitorInterface +class StackNodeVisitor extends Twig\NodeVisitor\AbstractNodeVisitor { /** - * Called before child nodes are visited. - * - * @param \Twig_NodeInterface $node The node to visit - * @param \Twig_Environment $env The Twig environment instance - * @return \Twig_NodeInterface The modified node + * @var Twig\Extension\ExtensionInterface + */ + private $ext; + + public function __construct(Twig\Extension\ExtensionInterface $ext) + { + $this->ext = $ext; + } + /** + * @inheritDoc */ - public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) + protected function doEnterNode(Node $node, Environment $env): Node { return $node; } /** - * Called after child nodes are visited. - * - * @param \Twig_NodeInterface $node The node to visit - * @param \Twig_Environment $env The Twig environment instance - * @return \Twig_NodeInterface|false The modified node or false if the node must be removed + * @inheritDoc */ - public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) + protected function doLeaveNode(Node $node, Environment $env): Node { - if ($node instanceof \Twig_Node_Module) { + if ($node instanceof Twig\Node\ModuleNode) { $this->handleModuleNode($node); } - return $node; } @@ -50,13 +53,13 @@ public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) * Handle the module node * Add a render stash node to the end of the module body, only when the template does not have a parent * - * @param \Twig_Node_Module $node + * @param Twig\Node\ModuleNode $node */ - private function handleModuleNode(\Twig_Node_Module $node) + private function handleModuleNode(Twig\Node\ModuleNode $node) { if ($node->hasNode('body') && !$node->hasNode('parent')) { $body = $node->getNode('body'); - $node->setNode('body', new StackBodyNode($body)); + $node->setNode('body', new StackBodyNode($this->ext, $body)); } } @@ -64,10 +67,10 @@ private function handleModuleNode(\Twig_Node_Module $node) * Returns the priority for this visitor. * Priority should be between -10 and 10 (0 is the default). * - * @return integer The priority level + * @return int The priority level */ - public function getPriority() + public function getPriority(): int { return -10; } -} \ No newline at end of file +} diff --git a/lib/TwigStack/Stack.php b/lib/TwigStack/Stack.php index 5971567..d8cb730 100644 --- a/lib/TwigStack/Stack.php +++ b/lib/TwigStack/Stack.php @@ -10,11 +10,13 @@ namespace TwigStack; +use ArrayObject; + /** * Class Stack * @package TwigStack */ -class Stack extends \ArrayObject +class Stack extends ArrayObject { /** * Separator which is used to join the stack, when cast to string @@ -37,8 +39,9 @@ public function push($content) * Set the separator which is used to join the stack * * @param string $separator + * @return void */ - public function setSeparator($separator) + public function setSeparator(string $separator): void { $this->separator = $separator; } @@ -54,4 +57,4 @@ public function __toString() { return join($this->separator, $this->getArrayCopy()); } -} \ No newline at end of file +} diff --git a/lib/TwigStack/TokenParser/StackPopTokenParser.php b/lib/TwigStack/TokenParser/StackPopTokenParser.php index 1e6743d..005a977 100644 --- a/lib/TwigStack/TokenParser/StackPopTokenParser.php +++ b/lib/TwigStack/TokenParser/StackPopTokenParser.php @@ -11,33 +11,43 @@ namespace TwigStack\TokenParser; use TwigStack\Node\StackPopNode; +use Twig; /** * Class StackPopTokenParser * @package TwigStack\TokenParser */ -class StackPopTokenParser extends \Twig_TokenParser +class StackPopTokenParser extends Twig\TokenParser\AbstractTokenParser { + /** + * @var Twig\Extension\ExtensionInterface + */ + private $ext; + + public function __construct(Twig\Extension\ExtensionInterface $ext) + { + $this->ext = $ext; + } + /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance - * @return \Twig_NodeInterface A Twig_NodeInterface instance - * @throws \Twig_Error_Syntax + * @param Twig\Token $token A Twig_Token instance + * @return Twig\Node\Node A Twig_NodeInterface instance + * @throws Twig\Error\SyntaxError */ - public function parse(\Twig_Token $token) + public function parse(Twig\Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $name = $stream->expect(\Twig_Token::NAME_TYPE)->getValue(); - if ($stream->test(\Twig_Token::STRING_TYPE)) { + $name = $stream->expect(Twig\Token::NAME_TYPE)->getValue(); + if ($stream->test(Twig\Token::STRING_TYPE)) { $separator = $this->parser->getExpressionParser()->parseStringExpression(); } else { - $separator = new \Twig_Node_Expression_Constant('', $lineno); + $separator = new Twig\Node\Expression\ConstantExpression('', $lineno); } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); - - return new StackPopNode($name, $separator, $lineno); + $stream->expect(Twig\Token::BLOCK_END_TYPE); + return new StackPopNode($this->ext, $name, $separator, $lineno); } /** @@ -45,8 +55,8 @@ public function parse(\Twig_Token $token) * * @return string The tag name */ - public function getTag() + public function getTag(): string { return 'stackpop'; } -} \ No newline at end of file +} diff --git a/lib/TwigStack/TokenParser/StackPushTokenParser.php b/lib/TwigStack/TokenParser/StackPushTokenParser.php index 53fd000..1a3ab60 100644 --- a/lib/TwigStack/TokenParser/StackPushTokenParser.php +++ b/lib/TwigStack/TokenParser/StackPushTokenParser.php @@ -11,52 +11,66 @@ namespace TwigStack\TokenParser; use TwigStack\Node\StackPushNode; +use Twig; /** * Class StackPushTokenParser * @package TwigStack\TokenParser */ -class StackPushTokenParser extends \Twig_TokenParser +class StackPushTokenParser extends Twig\TokenParser\AbstractTokenParser { + /** + * @var Twig\Extension\ExtensionInterface + */ + private $ext; + + public function __construct(Twig\Extension\ExtensionInterface $ext) + { + $this->ext = $ext; + } /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance - * @return \Twig_NodeInterface A Twig_NodeInterface instance - * @throws \Twig_Error_Syntax + * @param Twig\Token $token A Twig\Token instance + * @return Twig\Node\Node A Twig\Node\Node instance + * @throws Twig\Error\SyntaxError */ - public function parse(\Twig_Token $token) + public function parse(Twig\Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $name = $stream->expect(\Twig_Token::NAME_TYPE)->getValue(); + $name = $stream->expect(Twig\Token::NAME_TYPE)->getValue(); $this->parser->pushLocalScope(); - if ($stream->nextIf(\Twig_Token::BLOCK_END_TYPE)) { + if ($stream->nextIf(Twig\Token::BLOCK_END_TYPE)) { $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - if ($token = $stream->nextIf(\Twig_Token::NAME_TYPE)) { + if ($token = $stream->nextIf(Twig\Token::NAME_TYPE)) { $value = $token->getValue(); if ($value != $name) { - throw new \Twig_Error_Syntax(sprintf("Expected endstackpush for stack '$name', but got %s", $value), $stream->getCurrent()->getLine(), $stream->getFilename()); + throw + new Twig\Error\SyntaxError( + sprintf("Expected endstackpush for stack '$name', but got %s", $value), + $stream->getCurrent()->getLine(), + $stream->getSourceContext() + ); } } } else { - $body = new \Twig_Node(array( - new \Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno), + $body = new Twig\Node\Node(array( + new Twig\Node\PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), )); } $this->parser->popLocalScope(); - $stream->expect(\Twig_Token::BLOCK_END_TYPE); - - return new StackPushNode($name, $body, $lineno, $this->getTag()); + $stream->expect(Twig\Token::BLOCK_END_TYPE); + return new StackPushNode($this->ext, $name, $body, $lineno, $this->getTag()); } /** - * @param \Twig_Token $token + * @param Twig\Token $token * @return bool */ - public function decideBlockEnd(\Twig_Token $token) + public function decideBlockEnd(Twig\Token $token): bool { return $token->test('endstackpush'); } @@ -66,8 +80,8 @@ public function decideBlockEnd(\Twig_Token $token) * * @return string The tag name */ - public function getTag() + public function getTag(): string { return 'stackpush'; } -} \ No newline at end of file +} diff --git a/test/TwigStack/Tests/Fixtures/stack.test b/test/TwigStack/Tests/Fixtures/stack.test index acb657a..716c083 100644 --- a/test/TwigStack/Tests/Fixtures/stack.test +++ b/test/TwigStack/Tests/Fixtures/stack.test @@ -13,7 +13,6 @@ At the end --DATA-- return array('foo' => 'bar2') --EXPECT-- - bar1 bar2 foobar After foo At the end \ No newline at end of file diff --git a/test/TwigStack/Tests/IntegrationTest.php b/test/TwigStack/Tests/IntegrationTest.php index c3c3786..c0e7d2e 100644 --- a/test/TwigStack/Tests/IntegrationTest.php +++ b/test/TwigStack/Tests/IntegrationTest.php @@ -3,20 +3,21 @@ namespace TwigStack\Tests; use TwigStack\Extension\StackExtension; +use Twig; /** * Integration test for the twig stack * * @package TwigStack\Tests */ -class IntegrationTest extends \Twig_Test_IntegrationTestCase +class IntegrationTest extends Twig\Test\IntegrationTestCase { /** * Get the extensions under test * * @return array */ - public function getExtensions() + public function getExtensions(): array { return array( new StackExtension() @@ -26,8 +27,8 @@ public function getExtensions() /** * @return string */ - public function getFixturesDir() + public function getFixturesDir(): string { - return dirname(__FILE__).'/Fixtures/'; + return __DIR__ . '/Fixtures/'; } } \ No newline at end of file From fa55901d2e18c1d685a0950e4048d8a92d329bd5 Mon Sep 17 00:00:00 2001 From: jigius Date: Mon, 23 Aug 2021 11:09:05 +0700 Subject: [PATCH 2/2] fixes phpunit's config --- phpunit.xml.dist | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 621eee6..85dc462 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,26 +1,13 @@ - - - - - ./test/TwigStack/ - - - - - - ./lib/TwigStack/ - - + + + + ./lib/TwigStack/ + + + + + ./test/TwigStack/ + +