From a6d6b44dcb9d6abec43014b0320c9c1d7e14d300 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Thu, 12 Mar 2026 19:56:21 +0000 Subject: [PATCH 1/3] fix filtering by date --- src/Forms/SubmissionQueryBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Forms/SubmissionQueryBuilder.php b/src/Forms/SubmissionQueryBuilder.php index 82fb4890..c58b148c 100644 --- a/src/Forms/SubmissionQueryBuilder.php +++ b/src/Forms/SubmissionQueryBuilder.php @@ -20,7 +20,7 @@ protected function column($column) return $column; } - if ($column == 'datestamp') { + if ($column == 'datestamp' || $column == 'date') { $column = 'created_at'; } From 0bdfe14f36717fd4c44e87f95e7350b3dc133e98 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Thu, 12 Mar 2026 20:11:32 +0000 Subject: [PATCH 2/3] add test coverage --- src/Forms/Form.php | 2 +- tests/Forms/SubmissionQueryBuilderTest.php | 497 +++++++++++++++++++++ 2 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 tests/Forms/SubmissionQueryBuilderTest.php diff --git a/src/Forms/Form.php b/src/Forms/Form.php index 9b0260ee..3bec505e 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -35,7 +35,7 @@ public static function makeModelFromContract(Contract $source) $class = app('statamic.eloquent.forms.model'); return $class::firstOrNew(['handle' => $source->handle()])->fill([ - 'title' => $source->title(), + 'title' => $source->title() ?? $source->handle(), 'settings' => [ 'store' => $source->store(), 'email' => $source->email(), diff --git a/tests/Forms/SubmissionQueryBuilderTest.php b/tests/Forms/SubmissionQueryBuilderTest.php new file mode 100644 index 00000000..d2eb9043 --- /dev/null +++ b/tests/Forms/SubmissionQueryBuilderTest.php @@ -0,0 +1,497 @@ +save(); + FormSubmission::make()->form($form)->data(['a' => true])->save(); + FormSubmission::make()->form($form)->data(['b' => true])->save(); + FormSubmission::make()->form($form)->data(['c' => true])->save(); + + $submissions = FormSubmission::whereForm('test'); + $this->assertInstanceOf(Collection::class, $submissions); + $this->assertEveryItemIsInstanceOf(Submission::class, $submissions); + } + + #[Test] + public function it_filters_using_wheres() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'foo'])->save(); + + $submissions = FormSubmission::query()->where('test', 'foo')->get(); + $this->assertEquals(['a', 'c'], $submissions->map->get('id')->sort()->values()->all()); + } + + #[Test] + public function it_filters_using_or_wheres() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'baz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 'raz'])->save(); + + $submissions = FormSubmission::query()->where('test', 'foo')->orWhere('test', 'bar')->get(); + $this->assertEquals(['a', 'b', 'd'], $submissions->map->get('id')->values()->all()); + } + + #[Test] + public function it_filters_using_or_where_ins() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'baz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 'raz'])->save(); + + $submissions = FormSubmission::query()->whereIn('test', ['foo', 'bar'])->orWhereIn('test', ['foo', 'raz'])->get(); + + $this->assertEquals(['a', 'b', 'd', 'e'], $submissions->map->get('id')->values()->all()); + } + + #[Test] + public function it_filters_using_or_where_not_ins() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'baz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 'raz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'f', 'test' => 'taz'])->save(); + + $submissions = FormSubmission::query()->whereNotIn('test', ['foo', 'bar'])->orWhereNotIn('test', ['foo', 'bar', 'raz'])->get(); + + $this->assertEquals(['c', 'e', 'f'], $submissions->map->get('id')->values()->all()); + } + + #[Test] + public function it_filters_using_nested_wheres() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'baz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 'raz'])->save(); + + $submissions = FormSubmission::query() + ->where(function ($query) { + $query->where('test', 'foo'); + }) + ->orWhere(function ($query) { + $query->where('test', 'baz'); + }) + ->orWhere('test', 'raz') + ->get(); + + $this->assertCount(4, $submissions); + $this->assertEquals(['a', 'c', 'd', 'e'], $submissions->map->get('id')->sort()->values()->all()); + } + + #[Test] + public function it_filters_using_nested_where_ins() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'baz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 'raz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'f', 'test' => 'chaz'])->save(); + + $submissions = FormSubmission::query() + ->where(function ($query) { + $query->where('test', 'foo'); + }) + ->orWhere(function ($query) { + $query->whereIn('test', ['baz', 'raz']); + }) + ->orWhere('test', 'chaz') + ->get(); + + $this->assertCount(5, $submissions); + $this->assertEquals(['a', 'c', 'd', 'e', 'f'], $submissions->map->get('id')->sort()->values()->all()); + } + + #[Test] + public function it_filters_using_nested_where_not_ins() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 'bar'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 'baz'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 'foo'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 'raz'])->save(); + + $submissions = FormSubmission::query() + ->where('test', 'foo') + ->orWhere(function ($query) { + $query->whereNotIn('test', ['baz', 'raz']); + }) + ->get(); + + $this->assertCount(3, $submissions); + $this->assertEquals(['a', 'b', 'd'], $submissions->map->get('id')->sort()->values()->all()); + } + + #[Test] + public function it_sorts() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'test' => 4])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'test' => 2])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'test' => 1])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'test' => 5])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'test' => 3])->save(); + + $submissions = FormSubmission::query()->orderBy('test')->get(); + $this->assertEquals(['c', 'b', 'e', 'a', 'd'], $submissions->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_where_column() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a', 'title' => 'Post 1', 'other_title' => 'Not Post 1'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b', 'title' => 'Post 2', 'other_title' => 'Not Post 2'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c', 'title' => 'Post 3', 'other_title' => 'Post 3'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'd', 'title' => 'Post 4', 'other_title' => 'Post 4'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'e', 'title' => 'Post 5', 'other_title' => 'Not Post 5'])->save(); + + $submissions = FormSubmission::query()->whereColumn('title', 'other_title')->get(); + + $this->assertCount(2, $submissions); + $this->assertEquals(['c', 'd'], $submissions->map->get('id')->all()); + + $submissions = FormSubmission::query()->whereColumn('title', '!=', 'other_title')->get(); + + $this->assertCount(3, $submissions); + $this->assertEquals(['a', 'b', 'e'], $submissions->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_where_date() + { + $this->createWhereDateTestTerms(); + + $entries = FormSubmission::query()->whereDate('date', '2021-11-15')->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 1', 'Post 3'], $entries->map->title->sort()->values()->all()); + + $entries = FormSubmission::query()->whereDate('date', 1637000264)->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 1', 'Post 3'], $entries->map->title->sort()->values()->all()); + + $entries = FormSubmission::query()->whereDate('date', '>=', '2021-11-15')->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 1', 'Post 3'], $entries->map->title->sort()->values()->all()); + } + + #[Test] + public function submissions_are_found_using_where_month() + { + $this->createWhereDateTestTerms(); + + $entries = FormSubmission::query()->whereMonth('date', 11)->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['Post 1', 'Post 2', 'Post 3'], $entries->map->title->sort()->values()->all()); + + $entries = FormSubmission::query()->whereMonth('date', '<', 11)->get(); + + $this->assertCount(1, $entries); + $this->assertEquals(['Post 4'], $entries->map->title->sort()->values()->all()); + } + + #[Test] + public function submissions_are_found_using_where_day() + { + $this->createWhereDateTestTerms(); + + $entries = FormSubmission::query()->whereDay('date', 15)->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 1', 'Post 3'], $entries->map->title->sort()->values()->all()); + + $entries = FormSubmission::query()->whereDay('date', '<', 15)->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 2', 'Post 4'], $entries->map->title->sort()->values()->all()); + } + + #[Test] + public function submissions_are_found_using_where_year() + { + $this->createWhereDateTestTerms(); + + $entries = FormSubmission::query()->whereYear('date', 2021)->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['Post 1', 'Post 2', 'Post 3'], $entries->map->title->sort()->values()->all()); + + $entries = FormSubmission::query()->whereYear('date', '<', 2021)->get(); + + $this->assertCount(1, $entries); + $this->assertEquals(['Post 4'], $entries->map->title->sort()->values()->all()); + } + + #[Test] + public function submissions_are_found_using_where_time() + { + $this->createWhereDateTestTerms(); + + $entries = FormSubmission::query()->whereTime('date', '09:00:00')->get(); + + $this->assertCount(1, $entries); + $this->assertEquals(['Post 2'], $entries->map->title->sort()->values()->all()); + + $entries = FormSubmission::query()->whereTime('date', '>', '09:00:00')->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['Post 1', 'Post 4'], $entries->map->title->sort()->values()->all()); + } + + private function createWhereDateTestTerms() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['title' => 'Post 1'])->date(1637008264)->save(); + FormSubmission::make()->form($form)->data(['title' => 'Post 2'])->date(1636621200)->save(); + FormSubmission::make()->form($form)->data(['title' => 'Post 3'])->date(1636934400)->save(); + FormSubmission::make()->form($form)->data(['title' => 'Post 4'])->date(1600008264)->save(); + } + + #[Test] + public function submissions_are_found_using_where_json_contains() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonContains('test_taxonomy', ['taxonomy-1', 'taxonomy-3'])->get(); + + $this->assertCount(1, $entries); + $this->assertEquals(['3'], $entries->map->get('id')->all()); + + $entries = FormSubmission::query()->whereJsonContains('test_taxonomy', 'taxonomy-1')->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['1', '3'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_where_json_doesnt_contain() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonDoesntContain('test_taxonomy', ['taxonomy-1'])->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['2', '4', '5'], $entries->map->get('id')->all()); + + $entries = FormSubmission::query()->whereJsonDoesntContain('test_taxonomy', 'taxonomy-1')->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['2', '4', '5'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_or_where_json_contains() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonContains('test_taxonomy', ['taxonomy-1'])->orWhereJsonContains('test_taxonomy', ['taxonomy-5'])->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['1', '3', '5'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_or_where_json_doesnt_contain() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonContains('test_taxonomy', ['taxonomy-1'])->orWhereJsonDoesntContain('test_taxonomy', ['taxonomy-5'])->get(); + + $this->assertCount(4, $entries); + $this->assertEquals(['1', '2', '3', '4'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_where_json_overlaps() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonOverlaps('test_taxonomy', ['taxonomy-1', 'taxonomy-5'])->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['1', '3', '5'], $entries->map->get('id')->all()); + + $entries = FormSubmission::query()->whereJsonOverlaps('test_taxonomy', 'taxonomy-1')->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['1', '3'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_where_json_doesnt_overlap() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonDoesntOverlap('test_taxonomy', ['taxonomy-1'])->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['2', '4', '5'], $entries->map->get('id')->all()); + + $entries = FormSubmission::query()->whereJsonDoesntOverlap('test_taxonomy', 'taxonomy-1')->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['2', '4', '5'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_or_where_json_overlaps() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonOverlaps('test_taxonomy', ['taxonomy-1'])->orWhereJsonOverlaps('test_taxonomy', ['taxonomy-5'])->get(); + + $this->assertCount(3, $entries); + $this->assertEquals(['1', '3', '5'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_or_where_json_doesnt_overlap() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonOverlaps('test_taxonomy', ['taxonomy-1'])->orWhereJsonDoesntOverlap('test_taxonomy', ['taxonomy-5'])->get(); + + $this->assertCount(4, $entries); + $this->assertEquals(['1', '3', '2', '4'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_where_json_length() + { + if ($this->isUsingSqlite()) { + $this->markTestSkipped('SQLite doesn\'t support JSON contains queries'); + } + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => '1', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-2']])->save(); + FormSubmission::make()->form($form)->data(['id' => '2', 'test_taxonomy' => ['taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '3', 'test_taxonomy' => ['taxonomy-1', 'taxonomy-3']])->save(); + FormSubmission::make()->form($form)->data(['id' => '4', 'test_taxonomy' => ['taxonomy-3', 'taxonomy-4']])->save(); + FormSubmission::make()->form($form)->data(['id' => '5', 'test_taxonomy' => ['taxonomy-5']])->save(); + + $entries = FormSubmission::query()->whereJsonLength('test_taxonomy', 1)->get(); + + $this->assertCount(2, $entries); + $this->assertEquals(['2', '5'], $entries->map->get('id')->all()); + } + + #[Test] + public function submissions_are_found_using_offset() + { + $form = tap(Form::make('test'))->save(); + FormSubmission::make()->form($form)->data(['id' => 'a'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'b'])->save(); + FormSubmission::make()->form($form)->data(['id' => 'c'])->save(); + + $submissions = FormSubmission::query()->get(); + $this->assertEquals(['a', 'b', 'c'], $submissions->map->get('id')->all()); + + $submissions = FormSubmission::query()->limit(10)->offset(1)->get(); + $this->assertEquals(['b', 'c'], $submissions->map->get('id')->all()); + } +} From bd5ce6fc11fb87b7071be6bfd4a3ff95779bf39b Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Thu, 12 Mar 2026 20:12:39 +0000 Subject: [PATCH 3/3] :beer: --- tests/Forms/SubmissionQueryBuilderTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Forms/SubmissionQueryBuilderTest.php b/tests/Forms/SubmissionQueryBuilderTest.php index d2eb9043..9bf5932f 100644 --- a/tests/Forms/SubmissionQueryBuilderTest.php +++ b/tests/Forms/SubmissionQueryBuilderTest.php @@ -7,7 +7,6 @@ use Statamic\Contracts\Forms\Submission; use Statamic\Facades\Form; use Statamic\Facades\FormSubmission; -use Tests\PreventSavingStacheItemsToDisk; use Tests\TestCase; class SubmissionQueryBuilderTest extends TestCase