From 41e1ee851e6ce986e241d2a31f4bebe8484e2255 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 2 May 2024 23:02:02 -0400 Subject: [PATCH] use trait --- src/Entries/EntryQueryBuilder.php | 72 ++++++++++--------------------- 1 file changed, 22 insertions(+), 50 deletions(-) diff --git a/src/Entries/EntryQueryBuilder.php b/src/Entries/EntryQueryBuilder.php index 4bb7fcc3..7319623e 100644 --- a/src/Entries/EntryQueryBuilder.php +++ b/src/Entries/EntryQueryBuilder.php @@ -8,11 +8,13 @@ use Statamic\Facades\Collection; use Statamic\Facades\Entry; use Statamic\Query\EloquentQueryBuilder; +use Statamic\Stache\Query\QueriesEntryStatus; use Statamic\Stache\Query\QueriesTaxonomizedEntries; class EntryQueryBuilder extends EloquentQueryBuilder implements QueryBuilder { - use QueriesTaxonomizedEntries; + use QueriesEntryStatus, + QueriesTaxonomizedEntries; private $selectedQueryColumns; @@ -182,65 +184,35 @@ public function whereIn($column, $values, $boolean = 'and') return parent::whereIn($column, $values, $boolean); } - public function whereStatus(string $status) + private function ensureCollectionsAreQueriedForStatusQuery() { - if (! in_array($status, self::STATUSES)) { - throw new \Exception("Invalid status [$status]"); - } + $wheres = collect($this->builder->getQuery()->wheres); - if ($status === 'draft') { - return $this->where('published', false); + // If there are where clauses on the collection column, it means the user has explicitly + // queried for them. In that case, we'll use them and skip the auto-detection. + if ($wheres->where('column', 'collection')->isNotEmpty()) { + return; } - $this->where('published', true); + // Otherwise, we'll detect them by looking at where clauses targeting the "id" column. + $ids = $wheres->where('column', 'id')->flatMap(fn ($where) => $where['values'] ?? [$where['value']]); - return $this->where(fn ($query) => $this - ->getCollectionsForStatus() - ->each(fn ($collection) => $query->orWhere(fn ($q) => $this->addCollectionStatusLogicToQuery($q, $status, $collection)))); - } - - private function getCollectionsForStatus() - { - // Since we have to add nested queries for each collection, if collections have been provided, - // we'll use those to avoid the need for adding unnecessary query clauses. - - $wheres = collect($this->builder->getQuery()->wheres); - - if ($wheres->where('column', 'collection')->isEmpty()) { - return Collection::all(); + // If no IDs were queried, fall back to all collections. + if ($ids->isEmpty()) { + return $this->whereIn('collection', Collection::handles()); } - return $wheres->where('column', 'collection')->pluck('value')->map(fn ($handle) => Collection::find($handle)); + $this->whereIn('collection', app(static::class)->whereIn('id', $ids)->pluck('collection')->unique()->values()); } - private function addCollectionStatusLogicToQuery($query, $status, $collection) + private function getCollectionsForStatusQuery() { - $query->where('collection', $collection->handle()); - - if ($collection->futureDateBehavior() === 'public' && $collection->pastDateBehavior() === 'public') { - if ($status === 'scheduled' || $status === 'expired') { - $query->where('date', 'invalid'); // intentionally trigger no results. - } - } - - if ($collection->futureDateBehavior() === 'private') { - $status === 'scheduled' - ? $query->where('date', '>', now()) - : $query->where('date', '<', now()); + // Since we have to add nested queries for each collection, we only want to add clauses for the + // applicable collections. By this point, there should be where clauses on the collection column. - if ($status === 'expired') { - $query->where('date', 'invalid'); // intentionally trigger no results. - } - } - - if ($collection->pastDateBehavior() === 'private') { - $status === 'expired' - ? $query->where('date', '<', now()) - : $query->where('date', '>', now()); - - if ($status === 'scheduled') { - $query->where('date', 'invalid'); // intentionally trigger no results. - } - } + return collect($this->builder->getQuery()->wheres) + ->where('column', 'collection') + ->flatMap(fn ($where) => $where['values'] ?? [$where['value']]) + ->map(fn ($handle) => Collection::find($handle)); } }