From 54d12c60d486fedaa2893b303c0901a921d4bbdf Mon Sep 17 00:00:00 2001 From: Iain Date: Sat, 3 Oct 2026 02:10:16 +0100 Subject: [PATCH 1/3] fix(laravel): ignore invalid range filter values --- src/Laravel/Eloquent/Filter/RangeFilter.php | 5 +++++ src/Laravel/Tests/EloquentTest.php | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/Laravel/Eloquent/Filter/RangeFilter.php b/src/Laravel/Eloquent/Filter/RangeFilter.php index bb86f7dc78f..d3895256262 100644 --- a/src/Laravel/Eloquent/Filter/RangeFilter.php +++ b/src/Laravel/Eloquent/Filter/RangeFilter.php @@ -38,6 +38,11 @@ final class RangeFilter implements FilterInterface, JsonSchemaFilterInterface, O */ public function apply(Builder $builder, mixed $values, Parameter $parameter, array $context = []): Builder { + if (!\is_array($values)) { + return $builder; + } + + $values = array_intersect_key($values, self::OPERATOR_VALUE); $queryProperty = $this->getQueryProperty($parameter); foreach ($values as $key => $value) { diff --git a/src/Laravel/Tests/EloquentTest.php b/src/Laravel/Tests/EloquentTest.php index 30091ef78d6..3ad008071f3 100644 --- a/src/Laravel/Tests/EloquentTest.php +++ b/src/Laravel/Tests/EloquentTest.php @@ -427,6 +427,19 @@ public function testRangeGreaterThanEqualFilter(): void $this->assertSame($json['totalItems'], 2); } + public function testRangeFilterWithInvalidValue(): void + { + BookFactory::new()->has(AuthorFactory::new())->count(10)->create(); + + $res = $this->get('/api/books?isbn_range=5', ['Accept' => ['application/ld+json']]); + $res->assertOk(); + $this->assertSame(10, $res->json()['totalItems']); + + $res = $this->get('/api/books?isbn_range[unknown]=5', ['Accept' => ['application/ld+json']]); + $res->assertOk(); + $this->assertSame(10, $res->json()['totalItems']); + } + public function testWrongOrderFilter(): void { BookFactory::new()->has(AuthorFactory::new())->count(10)->create(); From c8d2a4aa3930e25841839a13c74c0d2c2dec939e Mon Sep 17 00:00:00 2001 From: Iain Date: Mon, 5 Oct 2026 09:54:34 +0100 Subject: [PATCH 2/3] fix(laravel): log ignored range filter values --- src/Laravel/Eloquent/Filter/RangeFilter.php | 14 ++++++++++++-- src/Laravel/Tests/EloquentTest.php | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Laravel/Eloquent/Filter/RangeFilter.php b/src/Laravel/Eloquent/Filter/RangeFilter.php index d3895256262..04cd0d97356 100644 --- a/src/Laravel/Eloquent/Filter/RangeFilter.php +++ b/src/Laravel/Eloquent/Filter/RangeFilter.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Laravel\Eloquent\Filter; +use ApiPlatform\Metadata\Exception\InvalidArgumentException; use ApiPlatform\Metadata\JsonSchemaFilterInterface; use ApiPlatform\Metadata\OpenApiParameterFilterInterface; use ApiPlatform\Metadata\Parameter; @@ -20,6 +21,7 @@ use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Psr\Log\LoggerInterface; final class RangeFilter implements FilterInterface, JsonSchemaFilterInterface, OpenApiParameterFilterInterface { @@ -32,17 +34,25 @@ final class RangeFilter implements FilterInterface, JsonSchemaFilterInterface, O 'gte' => '>=', ]; + public function __construct(private readonly ?LoggerInterface $logger = null) + { + } + /** * @param Builder $builder * @param array $context */ public function apply(Builder $builder, mixed $values, Parameter $parameter, array $context = []): Builder { - if (!\is_array($values)) { + $values = \is_array($values) ? array_intersect_key($values, self::OPERATOR_VALUE) : []; + if (!$values) { + $this->logger?->notice('Invalid filter ignored', [ + 'exception' => new InvalidArgumentException(\sprintf('At least one valid operator ("%s") is required for "%s" parameter', implode('", "', array_keys(self::OPERATOR_VALUE)), $parameter->getKey())), + ]); + return $builder; } - $values = array_intersect_key($values, self::OPERATOR_VALUE); $queryProperty = $this->getQueryProperty($parameter); foreach ($values as $key => $value) { diff --git a/src/Laravel/Tests/EloquentTest.php b/src/Laravel/Tests/EloquentTest.php index 3ad008071f3..b5387ccf49b 100644 --- a/src/Laravel/Tests/EloquentTest.php +++ b/src/Laravel/Tests/EloquentTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Laravel\Test\ApiTestAssertionsTrait; use ApiPlatform\Laravel\workbench\app\Enums\BookStatus; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase; @@ -430,6 +431,7 @@ public function testRangeGreaterThanEqualFilter(): void public function testRangeFilterWithInvalidValue(): void { BookFactory::new()->has(AuthorFactory::new())->count(10)->create(); + Log::spy(); $res = $this->get('/api/books?isbn_range=5', ['Accept' => ['application/ld+json']]); $res->assertOk(); @@ -438,6 +440,7 @@ public function testRangeFilterWithInvalidValue(): void $res = $this->get('/api/books?isbn_range[unknown]=5', ['Accept' => ['application/ld+json']]); $res->assertOk(); $this->assertSame(10, $res->json()['totalItems']); + Log::shouldHaveReceived('notice')->twice(); } public function testWrongOrderFilter(): void From d4c5016f78c458586f88abff00f40742845e3a38 Mon Sep 17 00:00:00 2001 From: Iain Date: Mon, 5 Oct 2026 10:51:08 +0100 Subject: [PATCH 3/3] test(laravel): assert on the returned log spy --- src/Laravel/Tests/EloquentTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Laravel/Tests/EloquentTest.php b/src/Laravel/Tests/EloquentTest.php index b5387ccf49b..1b34ff89bcf 100644 --- a/src/Laravel/Tests/EloquentTest.php +++ b/src/Laravel/Tests/EloquentTest.php @@ -431,7 +431,7 @@ public function testRangeGreaterThanEqualFilter(): void public function testRangeFilterWithInvalidValue(): void { BookFactory::new()->has(AuthorFactory::new())->count(10)->create(); - Log::spy(); + $log = Log::spy(); $res = $this->get('/api/books?isbn_range=5', ['Accept' => ['application/ld+json']]); $res->assertOk(); @@ -440,7 +440,7 @@ public function testRangeFilterWithInvalidValue(): void $res = $this->get('/api/books?isbn_range[unknown]=5', ['Accept' => ['application/ld+json']]); $res->assertOk(); $this->assertSame(10, $res->json()['totalItems']); - Log::shouldHaveReceived('notice')->twice(); + $log->shouldHaveReceived('notice')->twice(); } public function testWrongOrderFilter(): void