File tree Expand file tree Collapse file tree 7 files changed +69
-30
lines changed
Expand file tree Collapse file tree 7 files changed +69
-30
lines changed Original file line number Diff line number Diff line change 1717use LdapRecord \Query \Filter \AndGroup ;
1818use LdapRecord \Query \Filter \Factory ;
1919use LdapRecord \Query \Filter \Filter ;
20- use LdapRecord \Query \Filter \GroupFilter ;
2120use LdapRecord \Query \Filter \Not ;
2221use LdapRecord \Query \Filter \OrGroup ;
2322use LdapRecord \Query \Filter \Raw ;
@@ -30,6 +29,7 @@ class Builder
3029{
3130 use BuildsQueries;
3231 use EscapesValues;
32+ use ExtractsNestedFilters;
3333
3434 public const TYPE_SEARCH = 'search ' ;
3535
@@ -788,30 +788,6 @@ public function orFilter(Closure $closure): static
788788 return $ this ;
789789 }
790790
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-
815791 /**
816792 * Add a nested 'not' filter to the query.
817793 */
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ namespace LdapRecord \Query ;
4+
5+ use LdapRecord \Query \Filter \Filter ;
6+ use LdapRecord \Query \Filter \GroupFilter ;
7+
8+ trait ExtractsNestedFilters
9+ {
10+ /**
11+ * Extract filters from a nested group filter for re-wrapping, preserving nested groups.
12+ *
13+ * @return array<Filter>
14+ */
15+ protected function extractNestedFilters (Filter $ filter ): array
16+ {
17+ if (! $ filter instanceof GroupFilter) {
18+ return [$ filter ];
19+ }
20+
21+ $ children = $ filter ->getFilters ();
22+
23+ // If any child is a group, preserve the structure.
24+ foreach ($ children as $ child ) {
25+ if ($ child instanceof GroupFilter) {
26+ return $ children ;
27+ }
28+ }
29+
30+ // All children are non-groups, it's safe to unwrap.
31+ return $ children ;
32+ }
33+ }
Original file line number Diff line number Diff line change 1313use LdapRecord \Models \Types \ActiveDirectory ;
1414use LdapRecord \Query \Builder as QueryBuilder ;
1515use LdapRecord \Query \BuildsQueries ;
16+ use LdapRecord \Query \ExtractsNestedFilters ;
1617use LdapRecord \Query \Filter \AndGroup ;
1718use LdapRecord \Query \Filter \Filter ;
1819use LdapRecord \Query \Filter \Not ;
2829class Builder
2930{
3031 use BuildsQueries;
32+ use ExtractsNestedFilters;
3133 use ForwardsCalls;
3234
3335 /**
@@ -728,7 +730,9 @@ public function andFilter(Closure $closure): static
728730 $ query = $ this ->newNestedModelInstance ($ closure );
729731
730732 if ($ filter = $ query ->getQuery ()->getFilter ()) {
731- $ this ->query ->addFilter (new AndGroup ($ filter ));
733+ $ this ->query ->addFilter (new AndGroup (
734+ ...$ this ->extractNestedFilters ($ filter )
735+ ), wrap: false );
732736 }
733737
734738 return $ this ;
@@ -742,7 +746,9 @@ public function orFilter(Closure $closure): static
742746 $ query = $ this ->newNestedModelInstance ($ closure );
743747
744748 if ($ filter = $ query ->getQuery ()->getFilter ()) {
745- $ this ->query ->addFilter (new OrGroup ($ filter ), 'or ' );
749+ $ this ->query ->addFilter (new OrGroup (
750+ ...$ this ->extractNestedFilters ($ filter )
751+ ), wrap: false );
746752 }
747753
748754 return $ this ;
Original file line number Diff line number Diff line change @@ -227,7 +227,7 @@ public function test_only_related_with_many_relation_object_classes()
227227 {
228228 // Scopes are wrapped in their own AndGroup for isolation
229229 $ this ->assertEquals (
230- '(&(&( |(objectclass=top)(objectclass=person)(objectclass=organizationalperson)(objectclass=user))(|(objectclass=top)(objectclass=group) ))) ' ,
230+ '(&(|(objectclass=top)(objectclass=person)(objectclass=organizationalperson)(objectclass=user))(|(objectclass=top)(objectclass=group))) ' ,
231231 (new ModelHasManyStubWithManyRelated )->relation ()->onlyRelated ()->getQuery ()->getUnescapedQuery ()
232232 );
233233 }
Original file line number Diff line number Diff line change @@ -82,7 +82,7 @@ public function test_new_queries_apply_object_class_scopes()
8282
8383 // Scopes are wrapped in their own AndGroup for isolation
8484 $ this ->assertEquals (
85- '(&(&( objectclass=foo)(objectclass=bar)(objectclass=baz) )) ' ,
85+ '(&(objectclass=foo)(objectclass=bar)(objectclass=baz)) ' ,
8686 ModelWithObjectClassStub::query ()->getUnescapedQuery ()
8787 );
8888 }
Original file line number Diff line number Diff line change @@ -167,7 +167,7 @@ public function test_scopes_remain_enforced_with_complex_queries()
167167 {
168168 // The scope (foo=bar) must always be present and enforced at the root AND level
169169 $ this ->assertEquals (
170- '(&(|(name=\4a\6f\68\6e)(name=\4a\61\6e\65))(active=\74\72\75\65)(&(foo=bar))) ' ,
170+ '(&(&( |(name=\4a\6f\68\6e)(name=\4a\61\6e\65))(active=\74\72\75\65) )(&(foo=bar))) ' ,
171171 ModelWithGlobalScopeTestStub::query ()
172172 ->where ('name ' , '= ' , 'John ' )
173173 ->orWhere ('name ' , '= ' , 'Jane ' )
Original file line number Diff line number Diff line change @@ -165,4 +165,28 @@ public function test_add_select_with_variadic_arguments()
165165 $ this ->assertContains ('mail ' , $ selects );
166166 $ this ->assertContains ('objectguid ' , $ selects );
167167 }
168+
169+ public function test_or_filter_extracts_filters_from_nested_query ()
170+ {
171+ $ b = $ this ->newBuilder ();
172+
173+ $ query = $ b ->orFilter (function ($ query ) {
174+ $ query ->whereEquals ('foo ' , '1 ' );
175+ $ query ->whereEquals ('foo ' , '2 ' );
176+ })->getUnescapedQuery ();
177+
178+ $ this ->assertEquals ('(|(foo=1)(foo=2)) ' , $ query );
179+ }
180+
181+ public function test_and_filter_extracts_filters_from_nested_query ()
182+ {
183+ $ b = $ this ->newBuilder ();
184+
185+ $ query = $ b ->andFilter (function ($ query ) {
186+ $ query ->whereEquals ('foo ' , '1 ' );
187+ $ query ->whereEquals ('foo ' , '2 ' );
188+ })->getUnescapedQuery ();
189+
190+ $ this ->assertEquals ('(&(foo=1)(foo=2)) ' , $ query );
191+ }
168192}
You can’t perform that action at this time.
0 commit comments