diff --git a/src/Facades/FormSubmission.php b/src/Facades/FormSubmission.php
index f3fcef7af1..8b24412fc0 100644
--- a/src/Facades/FormSubmission.php
+++ b/src/Facades/FormSubmission.php
@@ -5,8 +5,8 @@
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Facade;
use Statamic\Contracts\Forms\Submission as SubmissionContract;
+use Statamic\Contracts\Forms\SubmissionQueryBuilder;
use Statamic\Contracts\Forms\SubmissionRepository;
-use Statamic\Stache\Query\SubmissionQueryBuilder;
/**
* @method static Collection all()
diff --git a/src/Forms/Form.php b/src/Forms/Form.php
index 37e24803c9..d504b69174 100644
--- a/src/Forms/Form.php
+++ b/src/Forms/Form.php
@@ -7,6 +7,7 @@
use Statamic\Contracts\Data\Augmented;
use Statamic\Contracts\Forms\Form as FormContract;
use Statamic\Contracts\Forms\Submission;
+use Statamic\Contracts\Forms\SubmissionQueryBuilder;
use Statamic\Data\HasAugmentedInstance;
use Statamic\Events\FormBlueprintFound;
use Statamic\Events\FormCreated;
@@ -296,6 +297,11 @@ public function submissions()
return FormSubmission::whereForm($this->handle());
}
+ public function querySubmissions(): SubmissionQueryBuilder
+ {
+ return FormSubmission::query()->where('form', $this->handle());
+ }
+
/**
* Get a submission.
*
diff --git a/src/Http/Controllers/CP/Forms/FormSubmissionsController.php b/src/Http/Controllers/CP/Forms/FormSubmissionsController.php
index 0269c78316..2940c8f7ed 100644
--- a/src/Http/Controllers/CP/Forms/FormSubmissionsController.php
+++ b/src/Http/Controllers/CP/Forms/FormSubmissionsController.php
@@ -2,15 +2,17 @@
namespace Statamic\Http\Controllers\CP\Forms;
-use Statamic\Extensions\Pagination\LengthAwarePaginator;
-use Statamic\Facades\Config;
+use Statamic\Fields\Field;
use Statamic\Http\Controllers\CP\CpController;
+use Statamic\Http\Requests\FilteredRequest;
use Statamic\Http\Resources\CP\Submissions\Submissions;
-use Statamic\Support\Str;
+use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters;
class FormSubmissionsController extends CpController
{
- public function index($form)
+ use QueriesFilters;
+
+ public function index(FilteredRequest $request, $form)
{
$this->authorize('view', $form);
@@ -18,52 +20,46 @@ public function index($form)
return ['data' => [], 'meta' => ['columns' => []]];
}
- $submissions = $form->submissions()->values();
+ $query = $this->indexQuery($form);
- // Search submissions.
- if ($search = $this->request->search) {
- $submissions = $this->searchSubmissions($submissions);
- }
+ $activeFilterBadges = $this->queryFilters($query, $request->filters, [
+ 'form' => $form->handle(),
+ ]);
- // Sort submissions.
- $sort = $this->request->sort ?? 'datestamp';
- $order = $this->request->order ?? ($sort === 'datestamp' ? 'desc' : 'asc');
- $submissions = $this->sortSubmissions($submissions, $sort, $order);
+ $sortField = request('sort', 'date');
+ $sortDirection = request('order', $sortField === 'date' ? 'desc' : 'asc');
- // Paginate submissions.
- $totalSubmissionCount = $submissions->count();
- $perPage = request('perPage') ?? Config::get('statamic.cp.pagination_size');
- $currentPage = (int) $this->request->page ?: 1;
- $offset = ($currentPage - 1) * $perPage;
- $submissions = $submissions->slice($offset, $perPage);
- $paginator = new LengthAwarePaginator($submissions, $totalSubmissionCount, $perPage, $currentPage);
+ if ($sortField) {
+ $query->orderBy($sortField, $sortDirection);
+ }
+
+ $submissions = $query->paginate(request('perPage'));
- return (new Submissions($paginator))
+ return (new Submissions($submissions))
->blueprint($form->blueprint())
- ->columnPreferenceKey("forms.{$form->handle()}.columns");
+ ->columnPreferenceKey("forms.{$form->handle()}.columns")
+ ->additional(['meta' => [
+ 'activeFilterBadges' => $activeFilterBadges,
+ ]]);
}
- private function searchSubmissions($submissions)
+ protected function indexQuery($form)
{
- return $submissions->filter(function ($submission) {
- return collect($submission->data())
- ->filter(function ($value) {
- return $value && is_string($value);
- })
- ->filter(function ($value) {
- return Str::contains(strtolower($value), strtolower($this->request->search));
+ $query = $form->querySubmissions();
+
+ if ($search = request('search')) {
+ $query->where('date', 'like', '%'.$search.'%');
+
+ $form->blueprint()->fields()->all()
+ ->filter(function (Field $field): bool {
+ return in_array($field->type(), ['text', 'textarea', 'integer']);
})
- ->isNotEmpty();
- })->values();
- }
+ ->each(function (Field $field) use ($query, $search): void {
+ $query->orWhere($field->handle(), 'like', '%'.$search.'%');
+ });
+ }
- private function sortSubmissions($submissions, $sortBy, $sortOrder)
- {
- return $submissions->sortBy(function ($submission) use ($sortBy) {
- return $sortBy === 'datestamp'
- ? $submission->date()->timestamp
- : $submission->get($sortBy);
- }, null, $sortOrder === 'desc')->values();
+ return $query;
}
public function destroy($form, $id)
diff --git a/src/Http/Controllers/CP/Forms/FormsController.php b/src/Http/Controllers/CP/Forms/FormsController.php
index 6ac63cdeec..a2c53b7399 100644
--- a/src/Http/Controllers/CP/Forms/FormsController.php
+++ b/src/Http/Controllers/CP/Forms/FormsController.php
@@ -8,6 +8,7 @@
use Statamic\Facades\Action;
use Statamic\Facades\Blueprint;
use Statamic\Facades\Form;
+use Statamic\Facades\Scope;
use Statamic\Facades\User;
use Statamic\Http\Controllers\CP\CpController;
use Statamic\Rules\Handle;
@@ -72,7 +73,15 @@ public function show($form)
->rejectUnlisted()
->values();
- return view('statamic::forms.show', compact('form', 'columns'));
+ $viewData = [
+ 'form' => $form,
+ 'columns' => $columns,
+ 'filters' => Scope::filters('form-submissions', [
+ 'form' => $form->handle(),
+ ]),
+ ];
+
+ return view('statamic::forms.show', $viewData);
}
/**
diff --git a/src/Query/Scopes/Filters/Fields.php b/src/Query/Scopes/Filters/Fields.php
index 2ce25209e3..50e3b6ac9d 100644
--- a/src/Query/Scopes/Filters/Fields.php
+++ b/src/Query/Scopes/Filters/Fields.php
@@ -4,6 +4,7 @@
use Statamic\Facades\Blueprint;
use Statamic\Facades\Collection;
+use Statamic\Facades\Form;
use Statamic\Facades\Taxonomy;
use Statamic\Facades\User;
use Statamic\Query\Scopes\Filter;
@@ -63,7 +64,7 @@ public function badge($values)
public function visibleTo($key)
{
- return in_array($key, ['entries', 'entries-fieldtype', 'terms', 'users', 'usergroup-users']);
+ return in_array($key, ['entries', 'entries-fieldtype', 'form-submissions', 'terms', 'users', 'usergroup-users']);
}
protected function getFields()
@@ -91,6 +92,17 @@ protected function getBlueprints()
});
}
+ if ($forms = Arr::getFirst($this->context, ['form', 'forms'])) {
+ return collect(Arr::wrap($forms))->map(function ($form) {
+ return Form::find($form)
+ ->blueprint()
+ ->ensureField('date', [
+ 'type' => 'date',
+ 'filterable' => true,
+ ]);
+ });
+ }
+
if (isset($this->context['blueprints'])) {
return collect($this->context['blueprints'])->map(function ($handle) {
return $handle === 'user'
diff --git a/src/Stache/Query/SubmissionQueryBuilder.php b/src/Stache/Query/SubmissionQueryBuilder.php
index 4a60afcc66..305b9d0af4 100644
--- a/src/Stache/Query/SubmissionQueryBuilder.php
+++ b/src/Stache/Query/SubmissionQueryBuilder.php
@@ -5,6 +5,7 @@
use Illuminate\Support\Collection;
use Statamic\Contracts\Forms\SubmissionQueryBuilder as QueryBuilderContract;
use Statamic\Facades;
+use Statamic\Query\OrderBy;
class SubmissionQueryBuilder extends Builder implements QueryBuilderContract
{
@@ -32,6 +33,17 @@ public function whereIn($column, $values, $boolean = 'and')
return parent::whereIn($column, $values, $boolean);
}
+ public function orderBy($column, $direction = 'asc')
+ {
+ if ($column === 'datestamp') {
+ $column = 'date';
+ }
+
+ $this->orderBys[] = new OrderBy($column, $direction);
+
+ return $this;
+ }
+
protected function collect($items = [])
{
return Collection::make($items);