@vituum/vite-plugin-latte 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +2 -2
- package/latte/PlaceholderFunction.php +2 -2
- package/package.json +10 -11
- package/vendor/autoload.php +18 -0
- package/vendor/bin/latte-lint +16 -4
- package/vendor/composer/ClassLoader.php +72 -65
- package/vendor/composer/InstalledVersions.php +21 -12
- package/vendor/composer/autoload_classmap.php +14 -8
- package/vendor/composer/autoload_namespaces.php +1 -1
- package/vendor/composer/autoload_psr4.php +1 -1
- package/vendor/composer/autoload_real.php +3 -22
- package/vendor/composer/autoload_static.php +13 -7
- package/vendor/composer/installed.json +8 -8
- package/vendor/composer/installed.php +10 -10
- package/vendor/latte/latte/bin/latte-lint +8 -2
- package/vendor/latte/latte/composer.json +1 -1
- package/vendor/latte/latte/readme.md +6 -6
- package/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php +1 -0
- package/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php +3 -2
- package/vendor/latte/latte/src/Latte/Compiler/Block.php +0 -3
- package/vendor/latte/latte/src/Latte/Compiler/Escaper.php +113 -89
- package/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php +2 -1
- package/vendor/latte/latte/src/Latte/Compiler/Node.php +0 -4
- package/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php +0 -4
- package/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php +0 -4
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php +11 -3
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php +10 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php +22 -4
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php +35 -12
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php +6 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php +12 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php +4 -31
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php +15 -1
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php +11 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php +42 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php +2 -2
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php +8 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php +15 -1
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php +11 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php +11 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/{StaticCallNode.php → StaticMethodCallNode.php} +11 -1
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/{StaticCallableNode.php → StaticMethodCallableNode.php} +11 -1
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php +38 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php +24 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php +48 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php +56 -0
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php +5 -5
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php +11 -21
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php +1 -8
- package/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php +30 -0
- package/vendor/latte/latte/src/Latte/Compiler/Position.php +4 -8
- package/vendor/latte/latte/src/Latte/Compiler/PrintContext.php +15 -8
- package/vendor/latte/latte/src/Latte/Compiler/Tag.php +13 -14
- package/vendor/latte/latte/src/Latte/Compiler/TagLexer.php +5 -9
- package/vendor/latte/latte/src/Latte/Compiler/TagParser.php +52 -3
- package/vendor/latte/latte/src/Latte/Compiler/TagParserData.php +353 -326
- package/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php +6 -5
- package/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php +105 -178
- package/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php +40 -33
- package/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php +186 -126
- package/vendor/latte/latte/src/Latte/Compiler/Token.php +5 -9
- package/vendor/latte/latte/src/Latte/Compiler/TokenStream.php +6 -22
- package/vendor/latte/latte/src/Latte/Engine.php +136 -95
- package/vendor/latte/latte/src/Latte/Essential/AuxiliaryIterator.php +46 -0
- package/vendor/latte/latte/src/Latte/Essential/Blueprint.php +42 -27
- package/vendor/latte/latte/src/Latte/Essential/CachingIterator.php +0 -4
- package/vendor/latte/latte/src/Latte/Essential/CoreExtension.php +81 -66
- package/vendor/latte/latte/src/Latte/Essential/Filters.php +103 -43
- package/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php +1 -2
- package/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php +2 -13
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php +8 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php +1 -2
- package/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php +0 -3
- package/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php +40 -13
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php +4 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php +5 -3
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php +5 -2
- package/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php +6 -4
- package/vendor/latte/latte/src/Latte/Essential/Nodes/JumpNode.php +26 -23
- package/vendor/latte/latte/src/Latte/Essential/Nodes/NElseNode.php +88 -0
- package/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php +20 -28
- package/vendor/latte/latte/src/Latte/Essential/Nodes/PrintNode.php +7 -12
- package/vendor/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TemplatePrintNode.php +25 -3
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Nodes/TryNode.php +3 -4
- package/vendor/latte/latte/src/Latte/Essential/Nodes/VarPrintNode.php +9 -2
- package/vendor/latte/latte/src/Latte/Essential/Nodes/WhileNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Essential/Passes.php +16 -58
- package/vendor/latte/latte/src/Latte/Essential/RawPhpExtension.php +0 -2
- package/vendor/latte/latte/src/Latte/Essential/TranslatorExtension.php +6 -1
- package/vendor/latte/latte/src/Latte/Helpers.php +3 -1
- package/vendor/latte/latte/src/Latte/Loader.php +1 -0
- package/vendor/latte/latte/src/Latte/Loaders/FileLoader.php +1 -4
- package/vendor/latte/latte/src/Latte/Loaders/StringLoader.php +0 -2
- package/vendor/latte/latte/src/Latte/PositionAwareException.php +1 -1
- package/vendor/latte/latte/src/Latte/Runtime/Block.php +0 -4
- package/vendor/latte/latte/src/Latte/Runtime/FilterExecutor.php +43 -51
- package/vendor/latte/latte/src/Latte/Runtime/FilterInfo.php +0 -2
- package/vendor/latte/latte/src/Latte/Runtime/Filters.php +64 -33
- package/vendor/latte/latte/src/Latte/Runtime/FunctionExecutor.php +68 -0
- package/vendor/latte/latte/src/Latte/Runtime/Html.php +0 -4
- package/vendor/latte/latte/src/Latte/Runtime/Template.php +3 -5
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php +2 -1
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php +1 -1
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php +3 -3
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/{StaticCallNode.php → StaticMethodCallNode.php} +3 -3
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/{StaticCallableNode.php → StaticMethodCallableNode.php} +2 -2
- package/vendor/latte/latte/src/Latte/Sandbox/RuntimeChecker.php +0 -2
- package/vendor/latte/latte/src/Latte/Sandbox/SandboxExtension.php +11 -9
- package/vendor/latte/latte/src/Latte/Sandbox/SecurityPolicy.php +0 -2
- package/vendor/latte/latte/src/Latte/exceptions.php +2 -11
- package/vendor/latte/latte/src/Tools/Linter.php +13 -37
- package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/QuotedValue.php +0 -53
- package/vendor/latte/latte/src/Latte/Strict.php +0 -101
|
@@ -9,7 +9,9 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
11
|
|
|
12
|
+
use Latte\CompileException;
|
|
12
13
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
14
|
+
use Latte\Compiler\Nodes\Php\ListNode;
|
|
13
15
|
use Latte\Compiler\Position;
|
|
14
16
|
use Latte\Compiler\PrintContext;
|
|
15
17
|
|
|
@@ -17,20 +19,32 @@ use Latte\Compiler\PrintContext;
|
|
|
17
19
|
class AssignNode extends ExpressionNode
|
|
18
20
|
{
|
|
19
21
|
public function __construct(
|
|
20
|
-
public ExpressionNode $var,
|
|
22
|
+
public ExpressionNode|ListNode $var,
|
|
21
23
|
public ExpressionNode $expr,
|
|
22
24
|
public bool $byRef = false,
|
|
23
25
|
public ?Position $position = null,
|
|
24
26
|
) {
|
|
27
|
+
$this->validate();
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
public function print(PrintContext $context): string
|
|
29
32
|
{
|
|
33
|
+
$this->validate();
|
|
30
34
|
return $context->infixOp($this, $this->var, $this->byRef ? ' = &' : ' = ', $this->expr);
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
|
|
38
|
+
public function validate(): void
|
|
39
|
+
{
|
|
40
|
+
if ($this->var instanceof ExpressionNode && !$this->var->isWritable()) {
|
|
41
|
+
throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position);
|
|
42
|
+
} elseif ($this->byRef && !$this->expr->isWritable()) {
|
|
43
|
+
throw new CompileException('Cannot take reference to the expression: ' . $this->expr->print(new PrintContext), $this->expr->position);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
34
48
|
public function &getIterator(): \Generator
|
|
35
49
|
{
|
|
36
50
|
yield $this->var;
|
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
11
|
|
|
12
|
+
use Latte\CompileException;
|
|
12
13
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
13
14
|
use Latte\Compiler\Position;
|
|
14
15
|
use Latte\Compiler\PrintContext;
|
|
@@ -28,15 +29,25 @@ class AssignOpNode extends ExpressionNode
|
|
|
28
29
|
if (!in_array($this->operator, self::Ops, true)) {
|
|
29
30
|
throw new \InvalidArgumentException("Unexpected operator '$this->operator'");
|
|
30
31
|
}
|
|
32
|
+
$this->validate();
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
public function print(PrintContext $context): string
|
|
35
37
|
{
|
|
38
|
+
$this->validate();
|
|
36
39
|
return $context->infixOp($this, $this->var, ' ' . $this->operator . '= ', $this->expr);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
|
|
43
|
+
public function validate(): void
|
|
44
|
+
{
|
|
45
|
+
if (!$this->var->isWritable()) {
|
|
46
|
+
throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
40
51
|
public function &getIterator(): \Generator
|
|
41
52
|
{
|
|
42
53
|
yield $this->var;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This file is part of the Latte (https://latte.nette.org)
|
|
5
|
+
* Copyright (c) 2008 David Grudl (https://davidgrudl.com)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare(strict_types=1);
|
|
9
|
+
|
|
10
|
+
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
|
+
|
|
12
|
+
use Latte\Compiler\Node;
|
|
13
|
+
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
14
|
+
use Latte\Compiler\PrintContext;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AuxiliaryNode extends ExpressionNode
|
|
18
|
+
{
|
|
19
|
+
public function __construct(
|
|
20
|
+
public /*readonly*/ \Closure $print,
|
|
21
|
+
/** @var (?Node)[] */
|
|
22
|
+
public array $nodes = [],
|
|
23
|
+
) {
|
|
24
|
+
(function (?Node ...$nodes) {})(...$nodes);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public function print(PrintContext $context): string
|
|
29
|
+
{
|
|
30
|
+
return ($this->print)($context, ...$this->nodes);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
public function &getIterator(): \Generator
|
|
35
|
+
{
|
|
36
|
+
foreach ($this->nodes as &$node) {
|
|
37
|
+
if ($node) {
|
|
38
|
+
yield $node;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php
CHANGED
|
@@ -20,7 +20,7 @@ class ClassConstantFetchNode extends ExpressionNode
|
|
|
20
20
|
{
|
|
21
21
|
public function __construct(
|
|
22
22
|
public NameNode|ExpressionNode $class,
|
|
23
|
-
public IdentifierNode $name,
|
|
23
|
+
public IdentifierNode|ExpressionNode $name,
|
|
24
24
|
public ?Position $position = null,
|
|
25
25
|
) {
|
|
26
26
|
}
|
|
@@ -30,7 +30,7 @@ class ClassConstantFetchNode extends ExpressionNode
|
|
|
30
30
|
{
|
|
31
31
|
return $context->dereferenceExpr($this->class)
|
|
32
32
|
. '::'
|
|
33
|
-
. $this->name
|
|
33
|
+
. $context->objectProperty($this->name);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
|
|
@@ -25,7 +25,7 @@ class ClosureNode extends ExpressionNode
|
|
|
25
25
|
/** @var ClosureUseNode[] */
|
|
26
26
|
public array $uses,
|
|
27
27
|
public Php\IdentifierNode|Php\NameNode|Php\ComplexTypeNode|null $returnType = null,
|
|
28
|
-
public ?ExpressionNode $expr,
|
|
28
|
+
public ?ExpressionNode $expr = null,
|
|
29
29
|
public ?Position $position = null,
|
|
30
30
|
) {
|
|
31
31
|
(function (Php\ParameterNode ...$args) {})(...$params);
|
|
@@ -26,6 +26,14 @@ class ConstantFetchNode extends ExpressionNode
|
|
|
26
26
|
|
|
27
27
|
public function print(PrintContext $context): string
|
|
28
28
|
{
|
|
29
|
+
if ($this->name->kind === NameNode::KindNormal) {
|
|
30
|
+
return match ((string) $this->name) {
|
|
31
|
+
'__LINE__' => (string) $this->position->line,
|
|
32
|
+
'__FILE__' => '(is_file(self::Source) ? self::Source : null)',
|
|
33
|
+
'__DIR__' => '(is_file(self::Source) ? dirname(self::Source) : null)',
|
|
34
|
+
default => $this->name->print($context),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
29
37
|
return $this->name->print($context);
|
|
30
38
|
}
|
|
31
39
|
|
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
11
|
|
|
12
|
+
use Latte\CompileException;
|
|
12
13
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
13
14
|
use Latte\Compiler\Position;
|
|
14
15
|
use Latte\Compiler\PrintContext;
|
|
@@ -21,16 +22,29 @@ class IssetNode extends ExpressionNode
|
|
|
21
22
|
public array $vars,
|
|
22
23
|
public ?Position $position = null,
|
|
23
24
|
) {
|
|
24
|
-
(
|
|
25
|
+
$this->validate();
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
public function print(PrintContext $context): string
|
|
29
30
|
{
|
|
31
|
+
$this->validate();
|
|
30
32
|
return 'isset(' . $context->implode($this->vars) . ')';
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
public function validate(): void
|
|
37
|
+
{
|
|
38
|
+
foreach ($this->vars as $var) {
|
|
39
|
+
if (!$var instanceof ExpressionNode) {
|
|
40
|
+
throw new \TypeError('Variable must be ExpressionNode, ' . get_debug_type($var) . ' given.');
|
|
41
|
+
} elseif (!$var->isVariable()) {
|
|
42
|
+
throw new CompileException('Cannot use isset() on expression: ' . $var->print(new PrintContext), $var->position);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
34
48
|
public function &getIterator(): \Generator
|
|
35
49
|
{
|
|
36
50
|
foreach ($this->vars as &$item) {
|
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
11
|
|
|
12
|
+
use Latte\CompileException;
|
|
12
13
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
13
14
|
use Latte\Compiler\Position;
|
|
14
15
|
use Latte\Compiler\PrintContext;
|
|
@@ -27,15 +28,25 @@ class PostOpNode extends ExpressionNode
|
|
|
27
28
|
if (!isset(self::Ops[$this->operator])) {
|
|
28
29
|
throw new \InvalidArgumentException("Unexpected operator '$this->operator'");
|
|
29
30
|
}
|
|
31
|
+
$this->validate();
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
public function print(PrintContext $context): string
|
|
34
36
|
{
|
|
37
|
+
$this->validate();
|
|
35
38
|
return $context->postfixOp($this, $this->var, $this->operator);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
|
|
42
|
+
public function validate(): void
|
|
43
|
+
{
|
|
44
|
+
if (!$this->var->isWritable()) {
|
|
45
|
+
throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
39
50
|
public function &getIterator(): \Generator
|
|
40
51
|
{
|
|
41
52
|
yield $this->var;
|
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
11
|
|
|
12
|
+
use Latte\CompileException;
|
|
12
13
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
13
14
|
use Latte\Compiler\Position;
|
|
14
15
|
use Latte\Compiler\PrintContext;
|
|
@@ -27,15 +28,25 @@ class PreOpNode extends ExpressionNode
|
|
|
27
28
|
if (!isset(self::Ops[$this->operator])) {
|
|
28
29
|
throw new \InvalidArgumentException("Unexpected operator '$this->operator'");
|
|
29
30
|
}
|
|
31
|
+
$this->validate();
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
public function print(PrintContext $context): string
|
|
34
36
|
{
|
|
37
|
+
$this->validate();
|
|
35
38
|
return $context->prefixOp($this, $this->operator, $this->var);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
|
|
42
|
+
public function validate(): void
|
|
43
|
+
{
|
|
44
|
+
if (!$this->var->isWritable()) {
|
|
45
|
+
throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
39
50
|
public function &getIterator(): \Generator
|
|
40
51
|
{
|
|
41
52
|
yield $this->var;
|
|
@@ -17,7 +17,7 @@ use Latte\Compiler\Position;
|
|
|
17
17
|
use Latte\Compiler\PrintContext;
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class
|
|
20
|
+
class StaticMethodCallNode extends ExpressionNode
|
|
21
21
|
{
|
|
22
22
|
public function __construct(
|
|
23
23
|
public NameNode|ExpressionNode $class,
|
|
@@ -53,3 +53,13 @@ class StaticCallNode extends ExpressionNode
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class_alias(StaticMethodCallNode::class, StaticCallNode::class);
|
|
59
|
+
|
|
60
|
+
if (false) {
|
|
61
|
+
/** @deprecated use Latte\Compiler\Nodes\Php\Expression\StaticMethodCallNode */
|
|
62
|
+
class StaticCallNode
|
|
63
|
+
{
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -16,7 +16,7 @@ use Latte\Compiler\Position;
|
|
|
16
16
|
use Latte\Compiler\PrintContext;
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class
|
|
19
|
+
class StaticMethodCallableNode extends ExpressionNode
|
|
20
20
|
{
|
|
21
21
|
public function __construct(
|
|
22
22
|
public NameNode|ExpressionNode $class,
|
|
@@ -45,3 +45,13 @@ class StaticCallableNode extends ExpressionNode
|
|
|
45
45
|
yield $this->name;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class_alias(StaticMethodCallableNode::class, StaticCallableNode::class);
|
|
51
|
+
|
|
52
|
+
if (false) {
|
|
53
|
+
/** @deprecated use Latte\Compiler\Nodes\Php\Expression\StaticMethodCallableNode */
|
|
54
|
+
class StaticCallableNode
|
|
55
|
+
{
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This file is part of the Latte (https://latte.nette.org)
|
|
5
|
+
* Copyright (c) 2008 David Grudl (https://davidgrudl.com)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare(strict_types=1);
|
|
9
|
+
|
|
10
|
+
namespace Latte\Compiler\Nodes\Php\Expression;
|
|
11
|
+
|
|
12
|
+
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
13
|
+
use Latte\Compiler\Nodes\Php\ListNode;
|
|
14
|
+
use Latte\Compiler\PrintContext;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Only for parser needs.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
class TemporaryNode extends ExpressionNode
|
|
22
|
+
{
|
|
23
|
+
public function __construct(
|
|
24
|
+
public ListNode|null $value,
|
|
25
|
+
) {
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
public function print(PrintContext $context): string
|
|
30
|
+
{
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
public function &getIterator(): \Generator
|
|
35
|
+
{
|
|
36
|
+
yield;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -14,4 +14,28 @@ use Latte\Compiler\Node;
|
|
|
14
14
|
|
|
15
15
|
abstract class ExpressionNode extends Node
|
|
16
16
|
{
|
|
17
|
+
public function isWritable(): bool
|
|
18
|
+
{
|
|
19
|
+
return $this instanceof Expression\ArrayAccessNode
|
|
20
|
+
|| ($this instanceof Expression\PropertyFetchNode && !$this->nullsafe)
|
|
21
|
+
|| $this instanceof Expression\StaticPropertyFetchNode
|
|
22
|
+
|| $this instanceof Expression\VariableNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
public function isVariable(): bool
|
|
27
|
+
{
|
|
28
|
+
return $this instanceof Expression\ArrayAccessNode
|
|
29
|
+
|| $this instanceof Expression\PropertyFetchNode
|
|
30
|
+
|| $this instanceof Expression\StaticPropertyFetchNode
|
|
31
|
+
|| $this instanceof Expression\VariableNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
public function isCall(): bool
|
|
36
|
+
{
|
|
37
|
+
return $this instanceof Expression\FunctionCallNode
|
|
38
|
+
|| $this instanceof Expression\MethodCallNode
|
|
39
|
+
|| $this instanceof Expression\StaticMethodCallNode;
|
|
40
|
+
}
|
|
17
41
|
}
|
|
@@ -34,7 +34,7 @@ class FilterNode extends Node
|
|
|
34
34
|
|
|
35
35
|
public function printSimple(PrintContext $context, string $expr): string
|
|
36
36
|
{
|
|
37
|
-
return '($this->filters->' . $this->name . ')('
|
|
37
|
+
return '($this->filters->' . $context->objectProperty($this->name) . ')('
|
|
38
38
|
. $expr
|
|
39
39
|
. ($this->args ? ', ' . $context->implode($this->args) : '')
|
|
40
40
|
. ')';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This file is part of the Latte (https://latte.nette.org)
|
|
5
|
+
* Copyright (c) 2008 David Grudl (https://davidgrudl.com)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare(strict_types=1);
|
|
9
|
+
|
|
10
|
+
namespace Latte\Compiler\Nodes\Php;
|
|
11
|
+
|
|
12
|
+
use Latte\Compiler\Node;
|
|
13
|
+
use Latte\Compiler\Position;
|
|
14
|
+
use Latte\Compiler\PrintContext;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ListItemNode extends Node
|
|
18
|
+
{
|
|
19
|
+
public function __construct(
|
|
20
|
+
public ExpressionNode|ListNode $value,
|
|
21
|
+
public ExpressionNode|IdentifierNode|null $key = null,
|
|
22
|
+
public bool $byRef = false,
|
|
23
|
+
public ?Position $position = null,
|
|
24
|
+
) {
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public function print(PrintContext $context): string
|
|
29
|
+
{
|
|
30
|
+
$key = match (true) {
|
|
31
|
+
$this->key instanceof ExpressionNode => $this->key->print($context) . ' => ',
|
|
32
|
+
$this->key instanceof IdentifierNode => $context->encodeString($this->key->name) . ' => ',
|
|
33
|
+
$this->key === null => '',
|
|
34
|
+
};
|
|
35
|
+
return $key
|
|
36
|
+
. ($this->byRef ? '&' : '')
|
|
37
|
+
. $this->value->print($context);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
public function &getIterator(): \Generator
|
|
42
|
+
{
|
|
43
|
+
if ($this->key) {
|
|
44
|
+
yield $this->key;
|
|
45
|
+
}
|
|
46
|
+
yield $this->value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This file is part of the Latte (https://latte.nette.org)
|
|
5
|
+
* Copyright (c) 2008 David Grudl (https://davidgrudl.com)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare(strict_types=1);
|
|
9
|
+
|
|
10
|
+
namespace Latte\Compiler\Nodes\Php;
|
|
11
|
+
|
|
12
|
+
use Latte\CompileException;
|
|
13
|
+
use Latte\Compiler\Node;
|
|
14
|
+
use Latte\Compiler\Position;
|
|
15
|
+
use Latte\Compiler\PrintContext;
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ListNode extends Node
|
|
19
|
+
{
|
|
20
|
+
public function __construct(
|
|
21
|
+
/** @var array<ListItemNode|null> */
|
|
22
|
+
public array $items = [],
|
|
23
|
+
public ?Position $position = null,
|
|
24
|
+
) {
|
|
25
|
+
$this->validate();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
public function print(PrintContext $context): string
|
|
30
|
+
{
|
|
31
|
+
$this->validate();
|
|
32
|
+
return '[' . $context->implode($this->items) . ']';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
public function validate(): void
|
|
37
|
+
{
|
|
38
|
+
foreach ($this->items as $item) {
|
|
39
|
+
if ($item !== null && !$item instanceof ListItemNode) {
|
|
40
|
+
throw new \TypeError('Item must be null or ListItemNode, ' . get_debug_type($item) . ' given.');
|
|
41
|
+
} elseif ($item?->value instanceof ExpressionNode && !$item->value->isWritable()) {
|
|
42
|
+
throw new CompileException('Cannot write to the expression: ' . $item->value->print(new PrintContext), $item->value->position);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
public function &getIterator(): \Generator
|
|
49
|
+
{
|
|
50
|
+
foreach ($this->items as &$item) {
|
|
51
|
+
if ($item) {
|
|
52
|
+
yield $item;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -51,12 +51,12 @@ class ModifierNode extends Node
|
|
|
51
51
|
$check = $this->check;
|
|
52
52
|
foreach ($this->filters as $filter) {
|
|
53
53
|
$name = $filter->name->name;
|
|
54
|
-
if (
|
|
54
|
+
if ($name === 'nocheck' || $name === 'noCheck') {
|
|
55
55
|
$check = false;
|
|
56
56
|
} elseif ($name === 'noescape') {
|
|
57
57
|
$escape = false;
|
|
58
58
|
} else {
|
|
59
|
-
if (
|
|
59
|
+
if ($name === 'datastream' || $name === 'dataStream') {
|
|
60
60
|
$check = false;
|
|
61
61
|
}
|
|
62
62
|
$expr = $filter->printSimple($context, $expr);
|
|
@@ -68,9 +68,9 @@ class ModifierNode extends Node
|
|
|
68
68
|
$expr = $escaper->check($expr);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
$expr = $escape
|
|
72
|
+
? $escaper->escape($expr)
|
|
73
|
+
: $escaper->escapeMandatory($expr);
|
|
74
74
|
|
|
75
75
|
return $expr;
|
|
76
76
|
}
|
|
@@ -20,31 +20,21 @@ class NameNode extends Node
|
|
|
20
20
|
KindNormal = 1,
|
|
21
21
|
KindFullyQualified = 2;
|
|
22
22
|
|
|
23
|
-
/** @var string[] */
|
|
24
|
-
public array $parts;
|
|
25
|
-
|
|
26
23
|
|
|
27
24
|
public function __construct(
|
|
28
|
-
string
|
|
25
|
+
public string $name,
|
|
29
26
|
public int $kind = self::KindNormal,
|
|
30
27
|
public ?Position $position = null,
|
|
31
28
|
) {
|
|
32
|
-
if ($name === ''
|
|
29
|
+
if ($name === '') {
|
|
33
30
|
throw new \InvalidArgumentException('Name cannot be empty');
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
} elseif (str_starts_with($name, 'namespace\\')) {
|
|
40
|
-
throw new \InvalidArgumentException('Relative name is not supported');
|
|
41
|
-
} else {
|
|
42
|
-
$this->kind = self::KindNormal;
|
|
43
|
-
}
|
|
44
|
-
$this->parts = explode('\\', $name);
|
|
45
|
-
|
|
31
|
+
} elseif (str_starts_with($name, 'namespace\\')) {
|
|
32
|
+
throw new \InvalidArgumentException('Relative name is not supported');
|
|
33
|
+
} elseif (str_starts_with($name, '\\')) {
|
|
34
|
+
$this->kind = self::KindFullyQualified;
|
|
35
|
+
$this->name = substr($name, 1);
|
|
46
36
|
} else {
|
|
47
|
-
$this->
|
|
37
|
+
$this->kind = self::KindNormal;
|
|
48
38
|
}
|
|
49
39
|
}
|
|
50
40
|
|
|
@@ -62,7 +52,7 @@ class NameNode extends Node
|
|
|
62
52
|
'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'yield',
|
|
63
53
|
'parent', 'self', 'mixed', 'void', 'enum', // extra
|
|
64
54
|
]);
|
|
65
|
-
return
|
|
55
|
+
return isset($keywords[strtolower($this->name)]);
|
|
66
56
|
}
|
|
67
57
|
|
|
68
58
|
|
|
@@ -74,7 +64,7 @@ class NameNode extends Node
|
|
|
74
64
|
|
|
75
65
|
public function __toString(): string
|
|
76
66
|
{
|
|
77
|
-
return
|
|
67
|
+
return $this->name;
|
|
78
68
|
}
|
|
79
69
|
|
|
80
70
|
|
|
@@ -84,7 +74,7 @@ class NameNode extends Node
|
|
|
84
74
|
self::KindNormal => $this->isKeyword() ? 'namespace\\' : '',
|
|
85
75
|
self::KindFullyQualified => '\\',
|
|
86
76
|
};
|
|
87
|
-
return $prefix .
|
|
77
|
+
return $prefix . $this->name;
|
|
88
78
|
}
|
|
89
79
|
|
|
90
80
|
|
|
@@ -9,7 +9,6 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Compiler\Nodes\Php\Scalar;
|
|
11
11
|
|
|
12
|
-
use Latte\Compiler\Nodes\Php\Expression;
|
|
13
12
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
14
13
|
use Latte\Compiler\Nodes\Php\InterpolatedStringPartNode;
|
|
15
14
|
use Latte\Compiler\Nodes\Php\ScalarNode;
|
|
@@ -52,14 +51,8 @@ class InterpolatedStringNode extends ScalarNode
|
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
$partStr = $part->print($context);
|
|
55
|
-
if ($partStr[0] === '$' &&
|
|
56
|
-
($part instanceof Expression\VariableNode
|
|
57
|
-
|| $part instanceof Expression\PropertyFetchNode
|
|
58
|
-
|| $part instanceof Expression\MethodCallNode
|
|
59
|
-
|| $part instanceof Expression\ArrayAccessNode
|
|
60
|
-
)) {
|
|
54
|
+
if ($partStr[0] === '$' && $part->isVariable()) {
|
|
61
55
|
$s .= '{' . $partStr . '}';
|
|
62
|
-
|
|
63
56
|
} else {
|
|
64
57
|
$s .= '" . (' . $partStr . ') . "';
|
|
65
58
|
$expr = true;
|
|
@@ -224,4 +224,34 @@ final class PhpHelpers
|
|
|
224
224
|
default => throw new CompileException('Invalid UTF-8 codepoint escape sequence: Codepoint too large'),
|
|
225
225
|
};
|
|
226
226
|
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
public static function checkCode(string $phpBinary, string $code, string $name): void
|
|
230
|
+
{
|
|
231
|
+
$process = proc_open(
|
|
232
|
+
$phpBinary . ' -l -n',
|
|
233
|
+
[['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']],
|
|
234
|
+
$pipes,
|
|
235
|
+
null,
|
|
236
|
+
null,
|
|
237
|
+
['bypass_shell' => true],
|
|
238
|
+
);
|
|
239
|
+
if (!is_resource($process)) {
|
|
240
|
+
throw new CompileException('Unable to check that the generated PHP is correct.');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
fwrite($pipes[0], $code);
|
|
244
|
+
fclose($pipes[0]);
|
|
245
|
+
$error = stream_get_contents($pipes[1]);
|
|
246
|
+
if (!proc_close($process)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
$error = strip_tags(explode("\n", $error)[1]);
|
|
250
|
+
$position = preg_match('~ on line (\d+)~', $error, $m)
|
|
251
|
+
? new Position((int) $m[1], 0)
|
|
252
|
+
: null;
|
|
253
|
+
$error = preg_replace('~(^Fatal error: | in Standard input code| on line \d+)~', '', $error);
|
|
254
|
+
throw (new CompileException('Error in generated code: ' . trim($error), $position))
|
|
255
|
+
->setSource($code, $name);
|
|
256
|
+
}
|
|
227
257
|
}
|