@@ -727,23 +727,36 @@ public function testGetUserGroupsMemberOfDisabled() {
727727		$ groupBackendgetUserGroups ('userX ' );
728728	}
729729
730- 	public  function  testGetGroupsByMember () {
730+ 	public  function  nestedGroupsProvider (): array  {
731+ 		return  [
732+ 			[ true  ],
733+ 			[ false  ],
734+ 		];
735+ 	}
736+ 
737+ 	/** 
738+ 	 * @dataProvider nestedGroupsProvider 
739+ 	 */ 
740+ 	public  function  testGetGroupsByMember (bool  $ nestedGroups
731741		$ access$ this getAccessMock ();
732742		$ pluginManager$ this getPluginManagerMock ();
733743
744+ 		$ groupFilter'(&(objectclass=nextcloudGroup)(nextcloudEnabled=TRUE)) ' ;
734745		$ accessconnection  = $ this createMock (Connection::class);
735746		$ accessconnection ->expects ($ this any ())
736747			->method ('__get ' )
737- 			->willReturnCallback (function  ($ name
748+ 			->willReturnCallback (function  ($ nameuse  ( $ nestedGroups ,  $ groupFilter )  {
738749				switch  ($ name
739750					case  'useMemberOfToDetectMembership ' :
740751						return  0 ;
741752					case  'ldapDynamicGroupMemberURL ' :
742753						return  '' ;
743754					case  'ldapNestedGroups ' :
744- 						return  false ;
755+ 						return  $ nestedGroups 
745756					case  'ldapGroupMemberAssocAttr ' :
746757						return  'member ' ;
758+ 					case  'ldapGroupFilter ' :
759+ 						return  $ groupFilter
747760				}
748761				return  1 ;
749762			});
@@ -756,10 +769,15 @@ public function testGetGroupsByMember() {
756769		$ accessexpects ($ this exactly (2 ))
757770			->method ('username2dn ' )
758771			->willReturn ($ dn
759- 
760772		$ accessexpects ($ this any ())
761773			->method ('readAttribute ' )
762774			->willReturn ([]);
775+ 		$ accessexpects ($ this any ())
776+ 			->method ('combineFilterWithAnd ' )
777+ 			->willReturnCallback (function  (array  $ filterParts
778+ 				// ⚠ returns a pseudo-filter only, not real LDAP Filter syntax 
779+ 				return  implode ('& ' , $ filterParts
780+ 			});
763781
764782		$ group1
765783			'cn '  => 'group1 ' ,
@@ -774,9 +792,21 @@ public function testGetGroupsByMember() {
774792			->method ('nextcloudGroupNames ' )
775793			->with ([$ group1$ group2
776794			->willReturn (['group1 ' , 'group2 ' ]);
777- 		$ accessexpects ($ this once ())
795+ 		$ accessexpects ($ nestedGroups  ?  $ this -> atLeastOnce () :  $ this once ())
778796			->method ('fetchListOfGroups ' )
779- 			->willReturn ([$ group1$ group2
797+ 			->willReturnCallback (function  ($ filter$ attr$ limit$ offsetuse  ($ nestedGroups$ groupFilter$ group1$ group2
798+ 				static  $ firstRuntrue ;
799+ 				if  (!$ nestedGroups
800+ 					// When nested groups are enabled, groups cannot be filtered early as it would 
801+ 					// exclude intermediate groups. But we can, and should, when working with flat groups. 
802+ 					$ this assertTrue (strpos ($ filter$ groupFilterfalse );
803+ 				}
804+ 				if  ($ firstRun
805+ 					$ firstRunfalse ;
806+ 					return  [$ group1$ group2
807+ 				}
808+ 				return  [];
809+ 			});
780810		$ accessexpects ($ this any ())
781811			->method ('dn2groupname ' )
782812			->willReturnCallback (function  (string  $ dn
0 commit comments