@@ -719,23 +719,36 @@ public function testGetUserGroupsMemberOfDisabled() {
719719		$ groupBackendgetUserGroups ('userX ' );
720720	}
721721
722- 	public  function  testGetGroupsByMember () {
722+ 	public  function  nestedGroupsProvider (): array  {
723+ 		return  [
724+ 			[ true  ],
725+ 			[ false  ],
726+ 		];
727+ 	}
728+ 
729+ 	/** 
730+ 	 * @dataProvider nestedGroupsProvider 
731+ 	 */ 
732+ 	public  function  testGetGroupsByMember (bool  $ nestedGroups
723733		$ access$ this getAccessMock ();
724734		$ pluginManager$ this getPluginManagerMock ();
725735
736+ 		$ groupFilter'(&(objectclass=nextcloudGroup)(nextcloudEnabled=TRUE)) ' ;
726737		$ accessconnection  = $ this createMock (Connection::class);
727738		$ accessconnection ->expects ($ this any ())
728739			->method ('__get ' )
729- 			->willReturnCallback (function  ($ name
740+ 			->willReturnCallback (function  ($ nameuse  ( $ nestedGroups ,  $ groupFilter )  {
730741				switch  ($ name
731742					case  'useMemberOfToDetectMembership ' :
732743						return  0 ;
733744					case  'ldapDynamicGroupMemberURL ' :
734745						return  '' ;
735746					case  'ldapNestedGroups ' :
736- 						return  false ;
747+ 						return  $ nestedGroups 
737748					case  'ldapGroupMemberAssocAttr ' :
738749						return  'member ' ;
750+ 					case  'ldapGroupFilter ' :
751+ 						return  $ groupFilter
739752				}
740753				return  1 ;
741754			});
@@ -748,10 +761,15 @@ public function testGetGroupsByMember() {
748761		$ accessexpects ($ this exactly (2 ))
749762			->method ('username2dn ' )
750763			->willReturn ($ dn
751- 
752764		$ accessexpects ($ this any ())
753765			->method ('readAttribute ' )
754766			->willReturn ([]);
767+ 		$ accessexpects ($ this any ())
768+ 			->method ('combineFilterWithAnd ' )
769+ 			->willReturnCallback (function  (array  $ filterParts
770+ 				// ⚠ returns a pseudo-filter only, not real LDAP Filter syntax 
771+ 				return  implode ('& ' , $ filterParts
772+ 			});
755773
756774		$ group1
757775			'cn '  => 'group1 ' ,
@@ -766,9 +784,21 @@ public function testGetGroupsByMember() {
766784			->method ('nextcloudGroupNames ' )
767785			->with ([$ group1$ group2
768786			->willReturn (['group1 ' , 'group2 ' ]);
769- 		$ accessexpects ($ this once ())
787+ 		$ accessexpects ($ nestedGroups  ?  $ this -> atLeastOnce () :  $ this once ())
770788			->method ('fetchListOfGroups ' )
771- 			->willReturn ([$ group1$ group2
789+ 			->willReturnCallback (function  ($ filter$ attr$ limit$ offsetuse  ($ nestedGroups$ groupFilter$ group1$ group2
790+ 				static  $ firstRuntrue ;
791+ 				if  (!$ nestedGroups
792+ 					// When nested groups are enabled, groups cannot be filtered early as it would 
793+ 					// exclude intermediate groups. But we can, and should, when working with flat groups. 
794+ 					$ this assertTrue (strpos ($ filter$ groupFilterfalse );
795+ 				}
796+ 				if  ($ firstRun
797+ 					$ firstRunfalse ;
798+ 					return  [$ group1$ group2
799+ 				}
800+ 				return  [];
801+ 			});
772802		$ accessexpects ($ this any ())
773803			->method ('dn2groupname ' )
774804			->willReturnCallback (function  (string  $ dn
0 commit comments