@vituum/vite-plugin-latte 1.0.0 → 1.1.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.
Files changed (114) hide show
  1. package/index.js +2 -2
  2. package/package.json +10 -11
  3. package/vendor/autoload.php +19 -1
  4. package/vendor/bin/latte-lint +16 -4
  5. package/vendor/composer/ClassLoader.php +72 -65
  6. package/vendor/composer/InstalledVersions.php +21 -12
  7. package/vendor/composer/autoload_classmap.php +12 -8
  8. package/vendor/composer/autoload_namespaces.php +1 -1
  9. package/vendor/composer/autoload_psr4.php +1 -1
  10. package/vendor/composer/autoload_real.php +7 -26
  11. package/vendor/composer/autoload_static.php +13 -9
  12. package/vendor/composer/installed.json +8 -8
  13. package/vendor/composer/installed.php +10 -10
  14. package/vendor/latte/latte/bin/latte-lint +8 -2
  15. package/vendor/latte/latte/composer.json +1 -1
  16. package/vendor/latte/latte/readme.md +6 -6
  17. package/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php +1 -0
  18. package/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php +3 -2
  19. package/vendor/latte/latte/src/Latte/Compiler/Block.php +0 -3
  20. package/vendor/latte/latte/src/Latte/Compiler/Escaper.php +103 -88
  21. package/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php +2 -1
  22. package/vendor/latte/latte/src/Latte/Compiler/Node.php +0 -4
  23. package/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php +0 -4
  24. package/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php +0 -4
  25. package/vendor/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php +11 -3
  26. package/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php +10 -0
  27. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php +22 -4
  28. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php +35 -12
  29. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php +6 -0
  30. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php +12 -0
  31. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php +4 -31
  32. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php +15 -1
  33. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php +11 -0
  34. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php +42 -0
  35. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php +2 -2
  36. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php +1 -1
  37. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php +8 -0
  38. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php +15 -1
  39. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php +11 -0
  40. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php +11 -0
  41. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/{StaticCallNode.php → StaticMethodCallNode.php} +11 -1
  42. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/{StaticCallableNode.php → StaticMethodCallableNode.php} +11 -1
  43. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php +38 -0
  44. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php +24 -0
  45. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php +48 -0
  46. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php +56 -0
  47. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php +3 -3
  48. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php +1 -8
  49. package/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php +30 -0
  50. package/vendor/latte/latte/src/Latte/Compiler/Position.php +4 -8
  51. package/vendor/latte/latte/src/Latte/Compiler/PrintContext.php +14 -7
  52. package/vendor/latte/latte/src/Latte/Compiler/Tag.php +13 -14
  53. package/vendor/latte/latte/src/Latte/Compiler/TagLexer.php +3 -7
  54. package/vendor/latte/latte/src/Latte/Compiler/TagParser.php +52 -3
  55. package/vendor/latte/latte/src/Latte/Compiler/TagParserData.php +354 -322
  56. package/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php +6 -5
  57. package/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php +95 -176
  58. package/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php +40 -33
  59. package/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php +182 -126
  60. package/vendor/latte/latte/src/Latte/Compiler/Token.php +5 -9
  61. package/vendor/latte/latte/src/Latte/Compiler/TokenStream.php +6 -22
  62. package/vendor/latte/latte/src/Latte/Engine.php +37 -8
  63. package/vendor/latte/latte/src/Latte/Essential/Blueprint.php +0 -2
  64. package/vendor/latte/latte/src/Latte/Essential/CachingIterator.php +0 -4
  65. package/vendor/latte/latte/src/Latte/Essential/CoreExtension.php +14 -3
  66. package/vendor/latte/latte/src/Latte/Essential/Filters.php +8 -6
  67. package/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php +1 -2
  68. package/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php +2 -13
  69. package/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php +1 -1
  70. package/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php +1 -2
  71. package/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php +1 -1
  72. package/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php +0 -3
  73. package/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php +1 -1
  74. package/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php +1 -1
  75. package/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php +4 -13
  76. package/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php +1 -1
  77. package/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php +4 -1
  78. package/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php +5 -3
  79. package/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php +5 -2
  80. package/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php +6 -4
  81. package/vendor/latte/latte/src/Latte/Essential/Nodes/JumpNode.php +26 -23
  82. package/vendor/latte/latte/src/Latte/Essential/Nodes/NElseNode.php +88 -0
  83. package/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php +20 -28
  84. package/vendor/latte/latte/src/Latte/Essential/Nodes/PrintNode.php +7 -12
  85. package/vendor/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php +1 -1
  86. package/vendor/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php +1 -1
  87. package/vendor/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php +1 -1
  88. package/vendor/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php +1 -1
  89. package/vendor/latte/latte/src/Latte/Essential/Nodes/TryNode.php +3 -4
  90. package/vendor/latte/latte/src/Latte/Essential/Nodes/WhileNode.php +1 -1
  91. package/vendor/latte/latte/src/Latte/Essential/Passes.php +9 -11
  92. package/vendor/latte/latte/src/Latte/Essential/RawPhpExtension.php +0 -2
  93. package/vendor/latte/latte/src/Latte/Essential/TranslatorExtension.php +6 -1
  94. package/vendor/latte/latte/src/Latte/Loaders/FileLoader.php +0 -2
  95. package/vendor/latte/latte/src/Latte/Loaders/StringLoader.php +0 -2
  96. package/vendor/latte/latte/src/Latte/PositionAwareException.php +1 -1
  97. package/vendor/latte/latte/src/Latte/Runtime/Block.php +0 -4
  98. package/vendor/latte/latte/src/Latte/Runtime/FilterExecutor.php +43 -51
  99. package/vendor/latte/latte/src/Latte/Runtime/FilterInfo.php +0 -2
  100. package/vendor/latte/latte/src/Latte/Runtime/Filters.php +64 -30
  101. package/vendor/latte/latte/src/Latte/Runtime/Html.php +0 -4
  102. package/vendor/latte/latte/src/Latte/Runtime/Template.php +2 -2
  103. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php +2 -1
  104. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php +1 -1
  105. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php +3 -3
  106. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/{StaticCallNode.php → StaticMethodCallNode.php} +3 -3
  107. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/{StaticCallableNode.php → StaticMethodCallableNode.php} +2 -2
  108. package/vendor/latte/latte/src/Latte/Sandbox/RuntimeChecker.php +0 -2
  109. package/vendor/latte/latte/src/Latte/Sandbox/SandboxExtension.php +11 -9
  110. package/vendor/latte/latte/src/Latte/Sandbox/SecurityPolicy.php +0 -2
  111. package/vendor/latte/latte/src/Latte/exceptions.php +2 -11
  112. package/vendor/latte/latte/src/Tools/Linter.php +13 -37
  113. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/QuotedValue.php +0 -53
  114. 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
+ }
@@ -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->print($context);
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
- (function (ExpressionNode ...$args) {})(...$vars);
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 StaticCallNode extends ExpressionNode
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 StaticCallableNode extends ExpressionNode
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
  }
@@ -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
+ }
@@ -68,9 +68,9 @@ class ModifierNode extends Node
68
68
  $expr = $escaper->check($expr);
69
69
  }
70
70
 
71
- if ($escape) {
72
- $expr = $escaper->escape($expr);
73
- }
71
+ $expr = $escape
72
+ ? $escaper->escape($expr)
73
+ : $escaper->escapeMandatory($expr);
74
74
 
75
75
  return $expr;
76
76
  }
@@ -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
  }
@@ -9,16 +9,12 @@ declare(strict_types=1);
9
9
 
10
10
  namespace Latte\Compiler;
11
11
 
12
- use Latte;
13
-
14
12
 
15
13
  final class Position
16
14
  {
17
- use Latte\Strict;
18
-
19
15
  public function __construct(
20
- public /*readonly*/ int $line,
21
- public /*readonly*/ int $column,
16
+ public /*readonly*/ int $line = 1,
17
+ public /*readonly*/ int $column = 1,
22
18
  public /*readonly*/ int $offset = 0,
23
19
  ) {
24
20
  }
@@ -42,8 +38,8 @@ final class Position
42
38
  }
43
39
 
44
40
 
45
- public function toWords(): string
41
+ public function __toString(): string
46
42
  {
47
- return "on line $this->line at column $this->column";
43
+ return "on line $this->line" . ($this->column ? " at column $this->column" : '');
48
44
  }
49
45
  }
@@ -9,7 +9,6 @@ declare(strict_types=1);
9
9
 
10
10
  namespace Latte\Compiler;
11
11
 
12
- use Latte;
13
12
  use Latte\Compiler\Nodes\Php as Nodes;
14
13
  use Latte\Compiler\Nodes\Php\Expression;
15
14
  use Latte\Compiler\Nodes\Php\Scalar;
@@ -22,8 +21,6 @@ use Latte\ContentType;
22
21
  */
23
22
  final class PrintContext
24
23
  {
25
- use Latte\Strict;
26
-
27
24
  public array $paramsExtraction = [];
28
25
  public array $blocks = [];
29
26
 
@@ -298,8 +295,8 @@ final class PrintContext
298
295
  || $expr instanceof Expression\FunctionCallableNode
299
296
  || $expr instanceof Expression\MethodCallNode
300
297
  || $expr instanceof Expression\MethodCallableNode
301
- || $expr instanceof Expression\StaticCallNode
302
- || $expr instanceof Expression\StaticCallableNode
298
+ || $expr instanceof Expression\StaticMethodCallNode
299
+ || $expr instanceof Expression\StaticMethodCallableNode
303
300
  || $expr instanceof Expression\ArrayNode
304
301
  ? $expr->print($this)
305
302
  : '(' . $expr->print($this) . ')';
@@ -320,8 +317,8 @@ final class PrintContext
320
317
  || $expr instanceof Expression\FunctionCallableNode
321
318
  || $expr instanceof Expression\MethodCallNode
322
319
  || $expr instanceof Expression\MethodCallableNode
323
- || $expr instanceof Expression\StaticCallNode
324
- || $expr instanceof Expression\StaticCallableNode
320
+ || $expr instanceof Expression\StaticMethodCallNode
321
+ || $expr instanceof Expression\StaticMethodCallableNode
325
322
  || $expr instanceof Expression\ArrayNode
326
323
  || $expr instanceof Scalar\StringNode
327
324
  || $expr instanceof Scalar\BooleanNode
@@ -331,4 +328,14 @@ final class PrintContext
331
328
  ? $expr->print($this)
332
329
  : '(' . $expr->print($this) . ')';
333
330
  }
331
+
332
+
333
+ /**
334
+ * @param Nodes\ArgumentNode[] $args
335
+ */
336
+ public function argumentsAsArray(array $args): string
337
+ {
338
+ $items = array_map(fn(Nodes\ArgumentNode $arg) => $arg->toArrayItem(), $args);
339
+ return '[' . $this->implode($items) . ']';
340
+ }
334
341
  }