diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index 0dceddf..7290381 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -230,6 +230,22 @@ class Plugin extends Model $template ); + // Convert for loops with filters to use temporary variables + // This handles: {% for item in collection | filter: "key", "value" %} + // Converts to: {% assign temp_filtered = collection | filter: "key", "value" %}{% for item in temp_filtered %} + $template = preg_replace_callback( + '/{%\s*for\s+(\w+)\s+in\s+([^|]+)\s*\|\s*([^}]+)%}/', + function ($matches) { + $variableName = trim($matches[1]); + $collection = trim($matches[2]); + $filter = trim($matches[3]); + $tempVarName = '_temp_' . uniqid(); + + return "{% assign {$tempVarName} = {$collection} | {$filter} %}{% for {$variableName} in {$tempVarName} %}"; + }, + $template + ); + return $template; } diff --git a/tests/Feature/PluginLiquidWhereFilterTest.php b/tests/Feature/PluginLiquidWhereFilterTest.php new file mode 100644 index 0000000..22a2fa5 --- /dev/null +++ b/tests/Feature/PluginLiquidWhereFilterTest.php @@ -0,0 +1,95 @@ +create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' +{% liquid +assign json_string = '[{"t":"2025-08-26 01:48","v":"4.624","type":"H"},{"t":"2025-08-26 08:04","v":"0.333","type":"L"}]' +assign collection = json_string | parse_json +%} + +{% assign tides_h = collection | where: "type", "H" %} + +{% for tide in tides_h %} + {{ tide | json }} +{%- endfor %} +LIQUID + , + ]); + + $result = $plugin->render('full'); + + // Should output the high tide data + $this->assertStringContainsString('"t":"2025-08-26 01:48"', $result); + $this->assertStringContainsString('"v":"4.624"', $result); + $this->assertStringContainsString('"type":"H"', $result); + // Should not contain the low tide data + $this->assertStringNotContainsString('"type":"L"', $result); +}); + +test('where filter works directly in for loop with preprocessing', function () { + $plugin = Plugin::factory()->create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' +{% liquid +assign json_string = '[{"t":"2025-08-26 01:48","v":"4.624","type":"H"},{"t":"2025-08-26 08:04","v":"0.333","type":"L"}]' +assign collection = json_string | parse_json +%} + +{% for tide in collection | where: "type", "H" %} + {{ tide | json }} +{%- endfor %} +LIQUID + , + ]); + + $result = $plugin->render('full'); + + // Should output the high tide data + $this->assertStringContainsString('"t":"2025-08-26 01:48"', $result); + $this->assertStringContainsString('"v":"4.624"', $result); + $this->assertStringContainsString('"type":"H"', $result); + // Should not contain the low tide data + $this->assertStringNotContainsString('"type":"L"', $result); +}); + +test('where filter works directly in for loop with multiple matches', function () { + $plugin = Plugin::factory()->create([ + 'markup_language' => 'liquid', + 'render_markup' => <<<'LIQUID' +{% liquid +assign json_string = '[{"t":"2025-08-26 01:48","v":"4.624","type":"H"},{"t":"2025-08-26 08:04","v":"0.333","type":"L"},{"t":"2025-08-26 14:30","v":"4.8","type":"H"}]' +assign collection = json_string | parse_json +%} + +{% for tide in collection | where: "type", "H" %} + {{ tide | json }} +{%- endfor %} +LIQUID + , + ]); + + $result = $plugin->render('full'); + + // Should output both high tide data entries + $this->assertStringContainsString('"t":"2025-08-26 01:48"', $result); + $this->assertStringContainsString('"t":"2025-08-26 14:30"', $result); + $this->assertStringContainsString('"v":"4.624"', $result); + $this->assertStringContainsString('"v":"4.8"', $result); + // Should not contain the low tide data + $this->assertStringNotContainsString('"type":"L"', $result); +});