Skip to content

Commit

Permalink
operator 'in' supports strings
Browse files Browse the repository at this point in the history
- InRangeNode renamed to InNode
  • Loading branch information
dg committed Oct 23, 2022
1 parent f167685 commit e3a5b8c
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Latte\Compiler\PrintContext;


class InRangeNode extends ExpressionNode
class InNode extends ExpressionNode
{
public function __construct(
public ExpressionNode $needle,
Expand All @@ -26,11 +26,11 @@ public function __construct(

public function print(PrintContext $context): string
{
return 'in_array('
return 'LR\Filters::contains('
. $this->needle->print($context)
. ', '
. $this->haystack->print($context)
. ', true)';
. ')';
}


Expand Down
2 changes: 1 addition & 1 deletion src/Latte/Compiler/TagParserData.php
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ protected function reduce(int $rule, int $pos): void
124 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
125 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
126 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
127 => fn() => $this->semValue = new Expression\InRangeNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
127 => fn() => $this->semValue = new Expression\InNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
128 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '+', $this->startTokenStack[$pos - 1]->position),
129 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '-', $this->startTokenStack[$pos - 1]->position),
130, 131 => fn() => $this->semValue = new Expression\NotNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
Expand Down
11 changes: 11 additions & 0 deletions src/Latte/Runtime/Filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,17 @@ public static function escapeHtmlRawText($s): string
}


/**
* Determine if a string or array contains a given needle.
*/
public static function contains(mixed $needle, array|string $haystack): bool
{
return is_array($haystack)
? in_array($needle, $haystack, true)
: str_contains($haystack, (string) $needle);
}


/**
* Converts ... to ...
*/
Expand Down
8 changes: 4 additions & 4 deletions tests/common/TagParser.parseArguments().phpt
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ test('inline modifiers', function () {


test('in operator', function () {
Assert::same("in_array(\$a, ['a', 'b'], true), 1", formatArgs('$a in [a, b], 1'));
Assert::same('$a, in_array($b->func(), [1, 2], true)', formatArgs('$a, $b->func() in [1, 2]'));
Assert::same('$a, in_array($b[1], [1, 2], true)', formatArgs('$a, $b[1] in [1, 2]'));
Assert::same('in_array($b, [1, [2], 3], true)', formatArgs('$b in [1, [2], 3]'));
Assert::same("LR\\Filters::contains(\$a, ['a', 'b']), 1", formatArgs('$a in [a, b], 1'));
Assert::same('$a, LR\Filters::contains($b->func(), [1, 2])', formatArgs('$a, $b->func() in [1, 2]'));
Assert::same('$a, LR\Filters::contains($b[1], [1, 2])', formatArgs('$a, $b[1] in [1, 2]'));
Assert::same('LR\Filters::contains($b, [1, [2], 3])', formatArgs('$b in [1, [2], 3]'));
});


Expand Down
26 changes: 26 additions & 0 deletions tests/filters/contains.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/**
* Test: Latte\Runtime\Filters::contains
*/

declare(strict_types=1);

use Latte\Runtime\Filters;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


Assert::false(Filters::contains(null, []));
Assert::true(Filters::contains(null, [null]));
Assert::false(Filters::contains(1, ['1']));
Assert::true(Filters::contains(1, [1]));

Assert::true(Filters::contains('', ''));
Assert::true(Filters::contains('', 'abcd'));
Assert::false(Filters::contains('bc', ''));
Assert::true(Filters::contains('bc', 'abcd'));
Assert::true(Filters::contains(null, ''));
Assert::true(Filters::contains(1, '123'));
Assert::false(Filters::contains(1, '23'));
8 changes: 4 additions & 4 deletions tests/phpParser/in.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ __halt_compiler();
Latte\Compiler\Nodes\Php\Expression\ArrayNode
items: array (3)
| 0 => Latte\Compiler\Nodes\Php\Expression\ArrayItemNode
| | value: Latte\Compiler\Nodes\Php\Expression\InRangeNode
| | value: Latte\Compiler\Nodes\Php\Expression\InNode
| | | needle: Latte\Compiler\Nodes\Php\Expression\VariableNode
| | | | name: 'a'
| | | | position: 1:1 (offset 0)
Expand All @@ -41,7 +41,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode
| | position: 1:1 (offset 0)
| 1 => Latte\Compiler\Nodes\Php\Expression\ArrayItemNode
| | value: Latte\Compiler\Nodes\Php\Expression\BinaryOpNode
| | | left: Latte\Compiler\Nodes\Php\Expression\InRangeNode
| | | left: Latte\Compiler\Nodes\Php\Expression\InNode
| | | | needle: Latte\Compiler\Nodes\Php\Expression\VariableNode
| | | | | name: 'a'
| | | | | position: 4:1 (offset 28)
Expand All @@ -50,7 +50,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode
| | | | | position: 4:7 (offset 34)
| | | | position: 4:1 (offset 28)
| | | operator: '||'
| | | right: Latte\Compiler\Nodes\Php\Expression\InRangeNode
| | | right: Latte\Compiler\Nodes\Php\Expression\InNode
| | | | needle: Latte\Compiler\Nodes\Php\Expression\VariableNode
| | | | | name: 'c'
| | | | | position: 4:13 (offset 40)
Expand All @@ -69,7 +69,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode
| | | | name: 'a'
| | | | position: 5:1 (offset 50)
| | | expr: Latte\Compiler\Nodes\Php\Expression\NotNode
| | | | expr: Latte\Compiler\Nodes\Php\Expression\InRangeNode
| | | | expr: Latte\Compiler\Nodes\Php\Expression\InNode
| | | | | needle: Latte\Compiler\Nodes\Php\Expression\BinaryOpNode
| | | | | | left: Latte\Compiler\Nodes\Php\Scalar\IntegerNode
| | | | | | | value: 10
Expand Down
4 changes: 2 additions & 2 deletions tests/phpPrint/operators.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ $a xor $b,
$a or $b,
$a instanceof Foo,
$a instanceof $b,
in_array($a, $b, true),
in_array(!$a, $b, true) && !in_array($a + 2, $b, true),
LR\Filters::contains($a, $b),
LR\Filters::contains(!$a, $b) && !LR\Filters::contains($a + 2, $b),
!$a,
!($a > $b) && !($c == !$d)

0 comments on commit e3a5b8c

Please sign in to comment.