Skip to content

Commit 276ddd7

Browse files
committed
Extract nested filters, preserving deeply nested filters
1 parent 6a4eecc commit 276ddd7

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

src/Query/Builder.php

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -764,11 +764,9 @@ public function andFilter(Closure $closure): static
764764
$query = $this->newNestedInstance($closure);
765765

766766
if ($filter = $query->getFilter()) {
767-
$filters = $filter instanceof GroupFilter
768-
? $filter->getFilters()
769-
: [$filter];
770-
771-
$this->addFilter(new AndGroup(...$filters), wrap: false);
767+
$this->addFilter(new AndGroup(
768+
...$this->extractNestedFilters($filter)
769+
), wrap: false);
772770
}
773771

774772
return $this;
@@ -782,16 +780,38 @@ public function orFilter(Closure $closure): static
782780
$query = $this->newNestedInstance($closure);
783781

784782
if ($filter = $query->getFilter()) {
785-
$filters = $filter instanceof GroupFilter
786-
? $filter->getFilters()
787-
: [$filter];
788-
789-
$this->addFilter(new OrGroup(...$filters), wrap: false);
783+
$this->addFilter(new OrGroup(
784+
...$this->extractNestedFilters($filter)
785+
), wrap: false);
790786
}
791787

792788
return $this;
793789
}
794790

791+
/**
792+
* Extract filters from a nested group filter for re-wrapping, preserving nested groups.
793+
*
794+
* @return array<Filter>
795+
*/
796+
protected function extractNestedFilters(Filter $filter): array
797+
{
798+
if (! $filter instanceof GroupFilter) {
799+
return [$filter];
800+
}
801+
802+
$children = $filter->getFilters();
803+
804+
// If any child is a group, preserve the structure
805+
foreach ($children as $child) {
806+
if ($child instanceof GroupFilter) {
807+
return $children;
808+
}
809+
}
810+
811+
// All children are non-groups, it's safe to unwrap.
812+
return $children;
813+
}
814+
795815
/**
796816
* Add a nested 'not' filter to the query.
797817
*/
@@ -1163,22 +1183,14 @@ public function addFilter(Filter $filter, string $boolean = 'and', bool $wrap =
11631183
return $this;
11641184
}
11651185

1166-
if (! $wrap) {
1167-
$this->filter = $boolean === 'or'
1168-
? new OrGroup($this->filter, $filter)
1169-
: new AndGroup($this->filter, $filter);
1170-
1171-
return $this;
1172-
}
1173-
11741186
// Flatten same-type groups to avoid deeply nested structures.
11751187
// Ex: AndGroup(AndGroup(a, b), c) becomes AndGroup(a, b, c)
11761188
if ($boolean === 'or') {
1177-
$this->filter = $this->filter instanceof OrGroup
1189+
$this->filter = $this->filter instanceof OrGroup && $wrap
11781190
? new OrGroup(...[...$this->filter->getFilters(), $filter])
11791191
: new OrGroup($this->filter, $filter);
11801192
} else {
1181-
$this->filter = $this->filter instanceof AndGroup
1193+
$this->filter = $this->filter instanceof AndGroup && $wrap
11821194
? new AndGroup(...[...$this->filter->getFilters(), $filter])
11831195
: new AndGroup($this->filter, $filter);
11841196
}

0 commit comments

Comments
 (0)