@@ -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