From 7bb45489a6378430a5316d495809eead1c12e52d Mon Sep 17 00:00:00 2001 From: nixx Date: Wed, 27 Dec 2023 19:57:28 +0300 Subject: [PATCH] Add where filter for array --- src/Liquid/StandardFilters.php | 21 +++++++++++++++++++++ src/Liquid/Tag/TagFor.php | 5 +++++ src/Liquid/Tag/TagPaginate.php | 2 +- tests/Liquid/ContextTest.php | 8 +++++++- tests/Liquid/FilterbankTest.php | 6 ++++++ tests/Liquid/OutputTest.php | 24 ++++++++++++++++++++++++ tests/Liquid/StandardFiltersTest.php | 22 ++++++++++++++++++++++ 7 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/Liquid/StandardFilters.php b/src/Liquid/StandardFilters.php index da670472..d3a8bf66 100644 --- a/src/Liquid/StandardFilters.php +++ b/src/Liquid/StandardFilters.php @@ -162,6 +162,27 @@ public static function json($input) return json_encode($input); } + /** + * Creates an array including only the objects with a given property value + * @link https://shopify.github.io/liquid/filters/where/ + * + * @param array $input + * @param string ...$args + * + * @throws LiquidException + * @return array + */ + public static function where(array $input, string ...$args): array + { + switch (count($args)) { + case 1: + return array_filter($input, fn ($v) => ($v[$args[0]] ?? null) !== null); + case 2: + return array_filter($input, fn ($v) => ($v[$args[0]] ?? '') == $args[1]); + default: + throw new LiquidException('Wrong number of arguments to function `where`, given ' . count($args) . ', expected 1 or 2'); + } + } /** * Escape a string diff --git a/src/Liquid/Tag/TagFor.php b/src/Liquid/Tag/TagFor.php index e1468877..edf732ca 100644 --- a/src/Liquid/Tag/TagFor.php +++ b/src/Liquid/Tag/TagFor.php @@ -50,6 +50,11 @@ class TagFor extends AbstractBlock */ private $name; + /** + * @var string + */ + private $start; + /** * @var string The type of the loop (collection or digit) */ diff --git a/src/Liquid/Tag/TagPaginate.php b/src/Liquid/Tag/TagPaginate.php index afafaef3..35726c5e 100644 --- a/src/Liquid/Tag/TagPaginate.php +++ b/src/Liquid/Tag/TagPaginate.php @@ -187,7 +187,7 @@ public function render(Context $context) public function currentUrl($context, $queryPart = []) { // From here we have $url->path and $url->query - $url = (object) parse_url($context->get('REQUEST_URI')); + $url = (object) parse_url($context->get('REQUEST_URI') ?: ''); // Let's merge the query part if (isset($url->query)) { diff --git a/tests/Liquid/ContextTest.php b/tests/Liquid/ContextTest.php index b95abea1..1321f784 100644 --- a/tests/Liquid/ContextTest.php +++ b/tests/Liquid/ContextTest.php @@ -85,7 +85,7 @@ public function toLiquid() class CountableObject implements \Countable { - public function count() + public function count(): int { return 2; } @@ -135,6 +135,8 @@ public function __get($prop) class HiFilter { + public Context $context; + public function hi($value) { return $value . ' hi!'; @@ -143,6 +145,8 @@ public function hi($value) class GlobalFilter { + public Context $context; + public function notice($value) { return "Global $value"; @@ -151,6 +155,8 @@ public function notice($value) class LocalFilter { + public Context $context; + public function notice($value) { return "Local $value"; diff --git a/tests/Liquid/FilterbankTest.php b/tests/Liquid/FilterbankTest.php index ed7cd8cf..a52855ec 100644 --- a/tests/Liquid/FilterbankTest.php +++ b/tests/Liquid/FilterbankTest.php @@ -11,6 +11,8 @@ namespace { + use Liquid\Context; + /** * Global function acts as a filter. * @@ -28,6 +30,8 @@ function functionFilter($value) */ class ClassFilter { + public Context $context; + private $variable = 'not set'; public function __construct() @@ -59,6 +63,8 @@ public function instance_test_two() class NamespacedClassFilter { + public Context $context; + public static function static_test2($var) { return "good {$var}"; diff --git a/tests/Liquid/OutputTest.php b/tests/Liquid/OutputTest.php index a18b048a..1b2fdf50 100644 --- a/tests/Liquid/OutputTest.php +++ b/tests/Liquid/OutputTest.php @@ -13,6 +13,8 @@ class FunnyFilter { + public Context $context; + public function make_funny($input) { return 'LOL'; @@ -191,4 +193,26 @@ public function testVariableWithANewLine() $text = "{{ aaa\n }}"; $this->assertTemplateResult('', $text, $this->assigns); } + + public function testFilterArray() + { + $text = ' {{ cars | where: "model", "bmw" | json }} '; + $expected = ' [{"model":"bmw"}] '; + + $this->assertTemplateResult($expected, $text, ['cars' => [ + ['model' => 'bmw'], + ['model' => 'audi'], + ]]); + } + + public function testFilterArrayTruthy() + { + $text = ' {{ cars | where: "available" | json }} '; + $expected = ' [{"model":"bmw","available":1}] '; + + $this->assertTemplateResult($expected, $text, ['cars' => [ + ['model' => 'bmw', 'available' => 1], + ['model' => 'audi'], + ]]); + } } diff --git a/tests/Liquid/StandardFiltersTest.php b/tests/Liquid/StandardFiltersTest.php index bc6c0be4..729266b2 100644 --- a/tests/Liquid/StandardFiltersTest.php +++ b/tests/Liquid/StandardFiltersTest.php @@ -13,6 +13,8 @@ class MoneyFilter { + public Context $context; + public function money($value) { return sprintf(' %d$ ', $value); @@ -26,6 +28,8 @@ public function money_with_underscore($value) class CanadianMoneyFilter { + public Context $context; + public function money($value) { return sprintf(' %d$ CAD ', $value); @@ -204,6 +208,24 @@ public function testJson() } } + public function testWhere() + { + $data = [ + [ + 'before' => [['model' => 'bmw'], ['model' => 'audi']], + 'after' => [['model' => 'bmw']], + ], + [ + 'before' => ['model' => 'bmw'], + 'after' => [], + ], + ]; + + foreach ($data as $testCase) { + $this->assertEquals($testCase['after'], StandardFilters::where($testCase['before'], 'model', 'bmw')); + } + } + public function testEscape() { $data = array(