diff --git a/src/Entries/EntryQueryBuilder.php b/src/Entries/EntryQueryBuilder.php index 5e6633fa..2bec7f03 100644 --- a/src/Entries/EntryQueryBuilder.php +++ b/src/Entries/EntryQueryBuilder.php @@ -2,14 +2,17 @@ namespace Statamic\Eloquent\Entries; +use Illuminate\Support\Collection as IlluminateCollection; use Illuminate\Support\Str; use Statamic\Contracts\Entries\QueryBuilder; use Statamic\Eloquent\Entries\Entry as EloquentEntry; +use Statamic\Eloquent\QueriesJsonColumns; use Statamic\Entries\EntryCollection; use Statamic\Facades\Blink; use Statamic\Facades\Collection; use Statamic\Facades\Entry; use Statamic\Facades\Taxonomy; +use Statamic\Fields\Field; use Statamic\Query\EloquentQueryBuilder; use Statamic\Stache\Query\QueriesEntryStatus; use Statamic\Stache\Query\QueriesTaxonomizedEntries; @@ -17,6 +20,7 @@ class EntryQueryBuilder extends EloquentQueryBuilder implements QueryBuilder { use QueriesEntryStatus, + QueriesJsonColumns, QueriesTaxonomizedEntries; private $selectedQueryColumns; @@ -28,92 +32,6 @@ class EntryQueryBuilder extends EloquentQueryBuilder implements QueryBuilder 'date', 'collection', 'created_at', 'updated_at', 'order', 'blueprint', ]; - public function orderBy($column, $direction = 'asc') - { - $actualColumn = $this->column($column); - - if (Str::contains($actualColumn, 'data->')) { - $wheres = collect($this->builder->getQuery()->wheres); - - if ($wheres->where('column', 'collection')->count() == 1) { - $collectionWhere = $wheres->firstWhere('column', 'collection'); - if (isset($collectionWhere['values']) && count($collectionWhere['values']) == 1) { - $collectionWhere['value'] = $collectionWhere['values'][0]; - } - - if (isset($collectionWhere['value'])) { - if ($collection = Collection::find($collectionWhere['value'])) { - $blueprintField = $collection->entryBlueprints() - ->flatMap(function ($blueprint) { - return $blueprint->fields() - ->all() - ->filter(function ($field) { - return in_array($field->type(), ['float', 'integer', 'date']); - }); - }) - ->filter() - ->get($column); - - if ($blueprintField) { - $castType = ''; - $fieldType = $blueprintField->type(); - - $grammar = $this->builder->getConnection()->getQueryGrammar(); - $actualColumn = $grammar->wrap($actualColumn); - - if (in_array($fieldType, ['float'])) { - $castType = 'float'; - } elseif (in_array($fieldType, ['integer'])) { - $castType = 'float'; // bit sneaky but mysql doesnt support casting as integer, it wants unsigned - } elseif (in_array($fieldType, ['date'])) { - // Take time into account when enabled - if ($blueprintField->get('time_enabled')) { - $castType = 'datetime'; - } else { - $castType = 'date'; - } - - // take range into account - if ($blueprintField->get('mode') == 'range') { - $actualColumnStartDate = $grammar->wrap($this->column($column).'->start'); - $actualColumnEndDate = $grammar->wrap($this->column($column).'->end'); - if (str_contains(get_class($grammar), 'SQLiteGrammar')) { - $this->builder - ->orderByRaw("datetime({$actualColumnStartDate}) {$direction}") - ->orderByRaw("datetime({$actualColumnEndDate}) {$direction}"); - } else { - $this->builder - ->orderByRaw("cast({$actualColumnStartDate} as {$castType}) {$direction}") - ->orderByRaw("cast({$actualColumnEndDate} as {$castType}) {$direction}"); - } - - return $this; - } - - // sqlite casts dates to year, which is pretty unhelpful - if (str_contains(get_class($grammar), 'SQLiteGrammar')) { - $this->builder->orderByRaw("datetime({$actualColumn}) {$direction}"); - - return $this; - } - } - - if ($castType) { - $this->builder->orderByRaw("cast({$actualColumn} as {$castType}) {$direction}"); - - return $this; - } - } - } - } - } - } - - parent::orderBy($column, $direction); - - return $this; - } - protected function transform($items, $columns = []) { $items = EntryCollection::make($items)->map(function ($model) use ($columns) { @@ -292,4 +210,27 @@ private function getKeysForTaxonomyWhereIn($where) ->pluck('id'); }); } + + protected function getJsonCasts(): IlluminateCollection + { + $wheres = collect($this->builder->getQuery()->wheres); + $collectionWhere = $wheres->firstWhere('column', 'collection'); + + if ( + ! $collectionWhere + || ! isset($collectionWhere['value']) + || ! ($collection = Collection::find($collectionWhere['value'])) + ) { + return []; + } + + return $collection->entryBlueprints() + ->flatMap(function ($blueprint) { + return $blueprint->fields() + ->all() + ->filter(fn ($field) => in_array($field->type(), ['float', 'integer', 'date'])) + ->map(fn (Field $field) => $this->toCast($field)); + }) + ->filter(); + } } diff --git a/tests/Data/Entries/EntryQueryBuilderTest.php b/tests/Data/Entries/EntryQueryBuilderTest.php index 980708a7..500fbb61 100644 --- a/tests/Data/Entries/EntryQueryBuilderTest.php +++ b/tests/Data/Entries/EntryQueryBuilderTest.php @@ -764,7 +764,7 @@ public function entries_can_be_ordered_by_an_integer_json_field() } #[Test] - public function entries_can_be_ordered_by_an_float_json_field() + public function entries_can_be_ordered_by_a_float_json_field() { $blueprint = Blueprint::makeFromFields(['float' => ['type' => 'float']]); Blueprint::shouldReceive('in')->with('collections/posts')->andReturn(collect(['posts' => $blueprint])); @@ -781,7 +781,7 @@ public function entries_can_be_ordered_by_an_float_json_field() } #[Test] - public function entries_can_be_ordered_by_an_date_json_field() + public function entries_can_be_ordered_by_a_date_json_field() { $blueprint = Blueprint::makeFromFields(['date_field' => ['type' => 'date', 'time_enabled' => true]]); Blueprint::shouldReceive('in')->with('collections/posts')->andReturn(collect(['posts' => $blueprint]));