From 2ee343cd557de915701027a891c3da6801eb76d4 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 2 Dec 2022 21:49:34 +0100 Subject: [PATCH] Node: getIterator() must exists (BC break) --- src/Latte/Compiler/Nodes/AuxiliaryNode.php | 6 ++++++ src/Latte/Compiler/Nodes/NopNode.php | 6 ++++++ src/Latte/Compiler/Nodes/Php/IdentifierNode.php | 6 ++++++ src/Latte/Compiler/Nodes/Php/NameNode.php | 6 ++++++ src/Latte/Compiler/Nodes/Php/ScalarNode.php | 4 ++++ src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php | 6 ++++++ src/Latte/Compiler/Nodes/TextNode.php | 6 ++++++ src/Latte/Compiler/TemplateParser.php | 15 +++++++++++++++ src/Latte/Compiler/TemplateParserHtml.php | 2 ++ src/Latte/Essential/Nodes/ContentTypeNode.php | 6 ++++++ src/Latte/Essential/Nodes/RawPhpNode.php | 6 ++++++ src/Latte/Essential/Nodes/RollbackNode.php | 6 ++++++ src/Latte/Essential/Nodes/TemplatePrintNode.php | 6 ++++++ src/Latte/Essential/Nodes/TemplateTypeNode.php | 6 ++++++ src/Latte/Essential/Nodes/TraceNode.php | 6 ++++++ src/Latte/Essential/Nodes/VarPrintNode.php | 6 ++++++ src/Latte/Essential/Nodes/VarTypeNode.php | 6 ++++++ tests/common/TemplateParser.nodes.phpt | 6 ++++++ tests/common/nodehelpers.php | 6 ++++++ 19 files changed, 117 insertions(+) diff --git a/src/Latte/Compiler/Nodes/AuxiliaryNode.php b/src/Latte/Compiler/Nodes/AuxiliaryNode.php index 87216bf717..50af4f8132 100644 --- a/src/Latte/Compiler/Nodes/AuxiliaryNode.php +++ b/src/Latte/Compiler/Nodes/AuxiliaryNode.php @@ -24,4 +24,10 @@ public function print(PrintContext $context): string { return ($this->callable)($context); } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/Nodes/NopNode.php b/src/Latte/Compiler/Nodes/NopNode.php index 1ab15c1c0a..b4b4dc1a79 100644 --- a/src/Latte/Compiler/Nodes/NopNode.php +++ b/src/Latte/Compiler/Nodes/NopNode.php @@ -18,4 +18,10 @@ public function print(PrintContext $context): string { return ''; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/Nodes/Php/IdentifierNode.php b/src/Latte/Compiler/Nodes/Php/IdentifierNode.php index cde875f645..539fed3197 100644 --- a/src/Latte/Compiler/Nodes/Php/IdentifierNode.php +++ b/src/Latte/Compiler/Nodes/Php/IdentifierNode.php @@ -33,4 +33,10 @@ public function print(PrintContext $context): string { return $this->name; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/Nodes/Php/NameNode.php b/src/Latte/Compiler/Nodes/Php/NameNode.php index f359155ba6..d590efb660 100644 --- a/src/Latte/Compiler/Nodes/Php/NameNode.php +++ b/src/Latte/Compiler/Nodes/Php/NameNode.php @@ -86,4 +86,10 @@ public function toCodeString(): string }; return $prefix . implode('\\', $this->parts); } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/Nodes/Php/ScalarNode.php b/src/Latte/Compiler/Nodes/Php/ScalarNode.php index d77e1863ba..764cbbb0fa 100644 --- a/src/Latte/Compiler/Nodes/Php/ScalarNode.php +++ b/src/Latte/Compiler/Nodes/Php/ScalarNode.php @@ -12,4 +12,8 @@ abstract class ScalarNode extends ExpressionNode { + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php b/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php index b0ce210961..61a57f50d3 100644 --- a/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php +++ b/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php @@ -26,4 +26,10 @@ public function print(PrintContext $context): string { throw new \LogicException('Cannot directly print SuperiorTypeNode'); } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/Nodes/TextNode.php b/src/Latte/Compiler/Nodes/TextNode.php index 3b279c613d..2b6f4f202c 100644 --- a/src/Latte/Compiler/Nodes/TextNode.php +++ b/src/Latte/Compiler/Nodes/TextNode.php @@ -34,4 +34,10 @@ public function isWhitespace(): bool { return trim($this->content) === ''; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Compiler/TemplateParser.php b/src/Latte/Compiler/TemplateParser.php index b919f96118..a6a56e263c 100644 --- a/src/Latte/Compiler/TemplateParser.php +++ b/src/Latte/Compiler/TemplateParser.php @@ -238,6 +238,8 @@ public function parseLatteStatement(): ?Node throw new \LogicException("Incorrect behavior of {{$startTag->name}} parser, unexpected returned value (on line {$startTag->position->line})"); } + $this->checkNodeCompatibility($node); + if ($this->location === self::LocationHead && $startTag->outputMode !== $startTag::OutputNone) { $this->location = self::LocationText; } @@ -445,4 +447,17 @@ public function isTagAllowed(string $name): bool { return !$this->policy || $this->policy->isTagAllowed($name); } + + + public function checkNodeCompatibility(Node $node): void + { + static $prev = [\Nette\Bridges\ApplicationLatte\Nodes\NNonceNode::class => true]; + if ( + !isset($prev[$node::class]) + && (new \ReflectionMethod($node, 'getIterator'))->getDeclaringClass()->getName() === Node::class + ) { + trigger_error('Class ' . $node::class . ' should contain method getIterator(), see https://bit.ly/latte-666'); + } + $prev[$node::class] = true; + } } diff --git a/src/Latte/Compiler/TemplateParserHtml.php b/src/Latte/Compiler/TemplateParserHtml.php index 1c952690ff..d0f8765461 100644 --- a/src/Latte/Compiler/TemplateParserHtml.php +++ b/src/Latte/Compiler/TemplateParserHtml.php @@ -454,6 +454,7 @@ private function openNAttrNodes(array $toOpen): array } elseif ($res instanceof Node) { $this->parser->ensureIsConsumed($tag); + $this->parser->checkNodeCompatibility($res); $res->position = $tag->position; $tag->replaceNAttribute($res); $this->parser->popTag(); @@ -477,6 +478,7 @@ private function finishNAttrNodes(AreaNode $node, array $toClose): AreaNode while ([$gen, $tag] = array_pop($toClose)) { $gen->send([$node, null]); $node = $gen->getReturn(); + $this->parser->checkNodeCompatibility($node); $node->position = $tag->position; $this->parser->popTag(); $this->parser->ensureIsConsumed($tag); diff --git a/src/Latte/Essential/Nodes/ContentTypeNode.php b/src/Latte/Essential/Nodes/ContentTypeNode.php index abc561e3e2..594214852e 100644 --- a/src/Latte/Essential/Nodes/ContentTypeNode.php +++ b/src/Latte/Essential/Nodes/ContentTypeNode.php @@ -71,4 +71,10 @@ public function print(PrintContext $context): string ) : ''; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/RawPhpNode.php b/src/Latte/Essential/Nodes/RawPhpNode.php index 56b11d5029..4c5807b9a8 100644 --- a/src/Latte/Essential/Nodes/RawPhpNode.php +++ b/src/Latte/Essential/Nodes/RawPhpNode.php @@ -43,4 +43,10 @@ public function print(PrintContext $context): string $this->code, ); } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/RollbackNode.php b/src/Latte/Essential/Nodes/RollbackNode.php index f105f4dab7..36c92802f6 100644 --- a/src/Latte/Essential/Nodes/RollbackNode.php +++ b/src/Latte/Essential/Nodes/RollbackNode.php @@ -34,4 +34,10 @@ public function print(PrintContext $context): string { return 'throw new Latte\Essential\RollbackException;'; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/TemplatePrintNode.php b/src/Latte/Essential/Nodes/TemplatePrintNode.php index 32827bf39c..9844c44f00 100644 --- a/src/Latte/Essential/Nodes/TemplatePrintNode.php +++ b/src/Latte/Essential/Nodes/TemplatePrintNode.php @@ -36,4 +36,10 @@ public function print(PrintContext $context): string { return '(new Latte\Essential\Blueprint)->printClass($this, ' . PhpHelpers::dump($this->template) . '); exit;'; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/TemplateTypeNode.php b/src/Latte/Essential/Nodes/TemplateTypeNode.php index aa3fb4678b..949d4f6065 100644 --- a/src/Latte/Essential/Nodes/TemplateTypeNode.php +++ b/src/Latte/Essential/Nodes/TemplateTypeNode.php @@ -35,4 +35,10 @@ public function print(PrintContext $context): string { return ''; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/TraceNode.php b/src/Latte/Essential/Nodes/TraceNode.php index ed7f32cedb..f2c70f7866 100644 --- a/src/Latte/Essential/Nodes/TraceNode.php +++ b/src/Latte/Essential/Nodes/TraceNode.php @@ -32,4 +32,10 @@ public function print(PrintContext $context): string $this->position, ); } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/VarPrintNode.php b/src/Latte/Essential/Nodes/VarPrintNode.php index 8ce71685b4..8efa80586d 100644 --- a/src/Latte/Essential/Nodes/VarPrintNode.php +++ b/src/Latte/Essential/Nodes/VarPrintNode.php @@ -37,4 +37,10 @@ public function print(PrintContext $context): string : 'array_diff_key(get_defined_vars(), $this->getParameters())'; return "(new Latte\\Essential\\Blueprint)->printVars($vars); exit;"; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/src/Latte/Essential/Nodes/VarTypeNode.php b/src/Latte/Essential/Nodes/VarTypeNode.php index 2585a513b3..fb21a1efc1 100644 --- a/src/Latte/Essential/Nodes/VarTypeNode.php +++ b/src/Latte/Essential/Nodes/VarTypeNode.php @@ -33,4 +33,10 @@ public function print(PrintContext $context): string { return ''; } + + + public function &getIterator(): \Generator + { + false && yield; + } } diff --git a/tests/common/TemplateParser.nodes.phpt b/tests/common/TemplateParser.nodes.phpt index daac26972a..46c06bf94a 100644 --- a/tests/common/TemplateParser.nodes.phpt +++ b/tests/common/TemplateParser.nodes.phpt @@ -13,6 +13,12 @@ class FooNode extends Latte\Compiler\Nodes\AreaNode { return ''; } + + + public function &getIterator(): Generator + { + false && yield; + } } diff --git a/tests/common/nodehelpers.php b/tests/common/nodehelpers.php index 43fbfe5a36..2de0f79a7f 100644 --- a/tests/common/nodehelpers.php +++ b/tests/common/nodehelpers.php @@ -12,6 +12,12 @@ public function print(PrintContext $context): string { return ''; } + + + public function &getIterator(): Generator + { + false && yield; + } }