Skip to content

Commit

Permalink
Implemented requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
spitfire305 committed Feb 6, 2025
1 parent bb7b7fb commit 26ddbad
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 58 deletions.
2 changes: 1 addition & 1 deletion app/Datagrids/Filters/DatagridFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ protected function tags(): self
}
$this->filters[] = [
'field' => 'tags',
'label' => Module::singular(config('entities.ids.tag'), __('entities.tags')),
'label' => Module::plural(config('entities.ids.tag'), __('entities.tags')),
'type' => 'tag',
'route' => route('search-list', [$this->campaign, config('entities.ids.tag')]),
'placeholder' => $placeholder,
Expand Down
101 changes: 48 additions & 53 deletions app/Models/Concerns/HasFilters.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Support\Str;
use App\Models\Location;
use App\Models\Family;
use App\Models\Organisation;
use App\Models\Race;
use Illuminate\Support\Facades\DB;

Expand Down Expand Up @@ -86,7 +87,7 @@ public function scopeFilter(Builder $query, array $params = []): Builder
foreach ($this->filterParams as $key => $value) {
if (isset($value) && in_array($key, $fields)) {
// The requested field is an array, which we don't support for anything other than tags, and locations ("or" searches)
if (is_array($value) && $key != "tags" && $key != "locations" && $key != "organisations" && $key != "races" && $key != "families") {
if (is_array($value) && !in_array($key, ['tags', 'locations', 'organisations', 'races', 'families'])) {
continue;
}
$this->filterOption = !empty($params[$key . '_option']) ? $params[$key . '_option'] : null;
Expand All @@ -113,7 +114,7 @@ public function scopeFilter(Builder $query, array $params = []): Builder
if ($key === 'tags') {
$this->filterTags($query, $value);
} elseif ($key == 'locations') {
$this->filterMultipleLocations($query, $value);
$this->filterLocations($query, $value);
} elseif ($key == 'organisations') {
$this->filterOrganisations($query, $value);
} elseif ($key == 'races') {
Expand All @@ -125,7 +126,7 @@ public function scopeFilter(Builder $query, array $params = []): Builder
} elseif ($key == 'races') {
$this->filterRaces($query, $value);
} elseif ($key == 'location_id') {
$this->filterLocations($query, $value, $key);
$this->filterLocation($query, $value, $key);
} elseif ($key == 'tag_id') {
$query
->joinEntity()
Expand Down Expand Up @@ -188,7 +189,7 @@ protected function extractSearchOperator($value, string $key): void
{
$operator = 'like';
$filterValue = $value;
if (($key !== 'tags') && ($key !== 'races') && ($key !== 'locations') && ($key !== 'families') && ($key !== 'organisations')) {
if (!in_array($key, ['tags', 'locations', 'organisations', 'races', 'families'])) {
if ($value == '!!') {
$operator = 'IS NULL';
$filterValue = null;
Expand Down Expand Up @@ -496,20 +497,14 @@ protected function filterRaces(Builder $query, null|string|array $value = null):
}

if ($this->filterOption('children')) {
$races = DB::select("
WITH RECURSIVE race_tree AS (
-- Select parents
SELECT * FROM races WHERE id IN (" . implode(',', $raceIds) . ")
UNION ALL
-- Recursively get all descendants
SELECT r.* FROM races r
INNER JOIN race_tree rt ON r.race_id = rt.id
)
SELECT * FROM race_tree
");
$raceIds = collect($races)->pluck('id'); // Extract IDs
$query->whereIn($this->getTable() . '.race_id', $raceIds)->distinct();
return;
$ids = [];
$parents = Race::whereIn('id', $raceIds)->with('descendants')->get();
foreach ($parents as $parent) {
$childIds = $parent->descendants->pluck('id')->toArray();
array_push($childIds, $parent->id);
$ids = $childIds + $ids;
}
$value = $ids;
}

foreach ($value as $v) {
Expand All @@ -522,9 +517,9 @@ protected function filterRaces(Builder $query, null|string|array $value = null):
}

/**
* Filter on characters on multiple locations
* Filter characters in location
*/
protected function filterLocations(Builder $query, string $value = null, string $key = null): void
protected function filterLocation(Builder $query, string $value = null, string $key = null): void
{
if (method_exists($this, 'scopeLocation')) {
$query->location($value, $this->getFilterOption());
Expand All @@ -548,7 +543,7 @@ protected function filterLocations(Builder $query, string $value = null, string
/**
* Filter on characters on multiple locations
*/
protected function filterMultipleLocations(Builder $query, null|string|array $value = null, string $key = null): void
protected function filterLocations(Builder $query, null|string|array $value = null, string $key = null): void
{
// "none" filter keys is handled later
if ($this->filterOption('none')) {
Expand All @@ -573,20 +568,14 @@ protected function filterMultipleLocations(Builder $query, null|string|array $va
}

if ($this->filterOption('children')) {
$locations = DB::select("
WITH RECURSIVE location_tree AS (
-- Select parents
SELECT * FROM locations WHERE id IN (" . implode(',', $locationIds) . ")
UNION ALL
-- Recursively get all descendants
SELECT l.* FROM locations l
INNER JOIN location_tree lt ON l.location_id = lt.id
)
SELECT * FROM location_tree
");
$locIds = collect($locations)->pluck('id'); // Extract IDs
$query->whereIn($this->getTable() . '.location_id', $locIds)->distinct();
return;
$ids = [];
$parents = Location::whereIn('id', $locationIds)->with('descendants')->get();
foreach ($parents as $parent) {
$childIds = $parent->descendants->pluck('id')->toArray();
array_push($childIds, $parent->id);
$ids = $childIds + $ids;
}
$locationIds = $ids;
}

$query->whereIn($this->getTable() . '.location_id', $locationIds)->distinct();
Expand Down Expand Up @@ -621,20 +610,14 @@ protected function filterOrganisations(Builder $query, null|string|array $value
}

if ($this->filterOption('children')) {
$orgs = DB::select("
WITH RECURSIVE organisation_tree AS (
-- Select parents
SELECT * FROM organisations WHERE id IN (" . implode(',', $orgIds) . ")
UNION ALL
-- Recursively get all descendants
SELECT r.* FROM organisations r
INNER JOIN organisation_tree rt ON r.organisation_id = rt.id
)
SELECT * FROM organisation_tree
");
$orgIds = collect($orgs)->pluck('id'); // Extract IDs
$query->whereIn($this->getTable() . '.organisation_id', $orgIds)->distinct();
return;
$ids = [];
$parents = Organisation::whereIn('id', $orgIds)->with('descendants')->get();
foreach ($parents as $parent) {
$childIds = $parent->descendants->pluck('id')->toArray();
array_push($childIds, $parent->id);
$ids = $childIds + $ids;
}
$value = $ids;
}

foreach ($value as $v) {
Expand Down Expand Up @@ -664,16 +647,28 @@ protected function filterFamilies(Builder $query, null|string|array $value = nul
$value = [$value];
}

$familyIds = [];
foreach ($value as $v) {
$familyIds[] = (int) $v;
}

if ($this->filterOption('exclude')) {
$familyIds = [];
foreach ($value as $v) {
$familyIds[] = (int) $v;
}
$query->whereRaw('(select count(*) from character_family as cr where cr.character_id = ' .
$this->getTable() . '.id and cr.family_id in (' . implode(', ', $familyIds) . ')) = 0');
return;
}

if ($this->filterOption('children')) {
$ids = [];
$parents = Family::whereIn('id', $familyIds)->with('descendants')->get();
foreach ($parents as $parent) {
$childIds = $parent->descendants->pluck('id')->toArray();
array_push($childIds, $parent->id);
$ids = $childIds + $ids;
}
$value = $ids;
}

foreach ($value as $v) {
$v = (int) $v;
$query
Expand Down
15 changes: 15 additions & 0 deletions app/Services/FilterService.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ protected function prepareFilters(array $availableFilters = []): self
$this->filters = [];
}

foreach (['tags', 'locations', 'organisations', 'races', 'families'] as $key) {
$this->checkFilterData($key, $availableFilters);
}

// If we have data but no "tags" array, it's empty
if (!empty($this->data) && in_array('tags', $availableFilters) && !isset($this->data['tags'])) {
// Not calling from a page or order result, we can junk the filters
Expand Down Expand Up @@ -246,6 +250,17 @@ protected function prepareOrder(array $availableFields = []): self
return $this;
}

private function checkFilterData(string $key, array $availableFilters): void
{
// If we have data but no array, it's empty
if (!empty($this->data) && in_array($key, $availableFilters) && !isset($this->data[$key])) {
// Not calling from a page or order result, we can junk the filters
if (empty($this->data['page']) && empty($this->data['order'])) {
unset($this->data[$key]);
}
}
}

/**
* @return $this
*/
Expand Down
6 changes: 2 additions & 4 deletions resources/views/filters/form.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,18 @@
@if (is_array($field))
<label>{!! Arr::get($field, 'label', __('crud.fields.' . $field['field'])) !!}</label>
<?php
$model = null;
$model = $models = null;
$value = $filterService->single($field['field']);
if (!empty($value) && $field['type'] == 'select2') {
$modelclass = new $field['model'];
$model = $modelclass->find($value);
}
// Support for fields with multiple models selected
if (Illuminate\Support\Arr::get($field, 'multiple') === true && $field['type'] == 'selectMultiple') {
if (Arr::get($field, 'multiple') === true && $field['type'] == 'selectMultiple') {
$value = $filterService->filterValue($field['field']);
if (!empty($value)) {
$modelclass = new $field['model'];
$models = $modelclass->whereIn('id', $value)->get()->pluck('name', 'id')->toArray();
} else {
unset($models);
}
}
?>
Expand Down

0 comments on commit 26ddbad

Please sign in to comment.