1414use OCP \Cache \CappedMemoryCache ;
1515use OCP \EventDispatcher \IEventDispatcher ;
1616use OCP \Files \Config \IMountProvider ;
17+ use OCP \Files \Config \IMountProviderArgs ;
18+ use OCP \Files \Config \IPartialMountProvider ;
1719use OCP \Files \Mount \IMountManager ;
1820use OCP \Files \Mount \IMountPoint ;
1921use OCP \Files \Storage \IStorageFactory ;
2628use Psr \Log \LoggerInterface ;
2729use function count ;
2830
29- class MountProvider implements IMountProvider {
31+ class MountProvider implements IMountProvider, IPartialMountProvider {
3032 /**
3133 * @param IConfig $config
3234 * @param IManager $shareManager
@@ -51,7 +53,7 @@ public function __construct(
5153 */
5254 public function getMountsForUser (IUser $ user , IStorageFactory $ loader ) {
5355 $ userId = $ user ->getUID ();
54- $ shares = array_merge (
56+ $ shares = $ this -> mergeIterables (
5557 $ this ->shareManager ->getSharedWith ($ userId , IShare::TYPE_USER , null , -1 ),
5658 $ this ->shareManager ->getSharedWith ($ userId , IShare::TYPE_GROUP , null , -1 ),
5759 $ this ->shareManager ->getSharedWith ($ userId , IShare::TYPE_CIRCLE , null , -1 ),
@@ -63,17 +65,19 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {
6365 $ shares = $ this ->filterShares ($ shares , $ userId );
6466 $ superShares = $ this ->buildSuperShares ($ shares , $ user );
6567
66- return $ this ->getMountsFromSuperShares ($ userId , $ superShares , $ loader , $ user );
68+ return array_values ($ this ->getMountsFromSuperShares ($ userId ,
69+ $ superShares ,
70+ $ loader , $ user ));
6771 }
6872
6973 /**
7074 * Groups shares by path (nodeId) and target path
7175 *
72- * @param IShare[] $shares
76+ * @param iterable< IShare> $shares
7377 * @return IShare[][] array of grouped shares, each element in the
7478 * array is a group which itself is an array of shares
7579 */
76- private function groupShares (array $ shares ) {
80+ private function groupShares (iterable $ shares ): array {
7781 $ tmp = [];
7882
7983 foreach ($ shares as $ share ) {
@@ -109,11 +113,11 @@ private function groupShares(array $shares) {
109113 * the shares in the group, forming the most permissive combination
110114 * possible.
111115 *
112- * @param IShare[] $allShares
116+ * @param iterable< IShare> $allShares
113117 * @param IUser $user user
114118 * @return list<array{IShare, array<IShare>}> Tuple of [superShare, groupedShares]
115119 */
116- private function buildSuperShares (array $ allShares , IUser $ user ) {
120+ private function buildSuperShares (iterable $ allShares , IUser $ user ): array {
117121 $ result = [];
118122
119123 $ groupedShares = $ this ->groupShares ($ allShares );
@@ -249,7 +253,7 @@ private function adjustTarget(
249253 * @param array $superShares
250254 * @param IStorageFactory $loader
251255 * @param IUser $user
252- * @return array
256+ * @return array IMountPoint indexed by mount point
253257 * @throws Exception
254258 */
255259 private function getMountsFromSuperShares (
@@ -334,24 +338,102 @@ private function getMountsFromSuperShares(
334338 $ validShareCache ->set ($ userId , $ newMaxValidatedShare , 24 * 60 * 60 );
335339
336340 // array_filter removes the null values from the array
337- return array_values ( array_filter ($ mounts) );
341+ return array_filter ($ mounts );
338342 }
339343
340344 /**
341345 * Filters out shares owned or shared by the user and ones for which the
342346 * user has no permissions.
343347 *
344- * @param IShare[] $shares
345- * @return IShare[]
348+ * @param iterable< IShare> $shares
349+ * @return iterable< IShare>
346350 */
347- private function filterShares (array $ shares , string $ userId ): array {
348- return array_filter (
349- $ shares ,
350- static function (IShare $ share ) use ($ userId ) {
351- return $ share ->getPermissions () > 0
352- && $ share ->getShareOwner () !== $ userId
353- && $ share ->getSharedBy () !== $ userId ;
351+ private function filterShares (iterable $ shares , string $ userId ): iterable {
352+ foreach ($ shares as $ share ) {
353+ if ($ share ->getPermissions () > 0 && $ share ->getShareOwner ()
354+ !== $ userId && $ share ->getSharedBy () !== $ userId ) {
355+ yield $ share ;
356+ }
357+ }
358+ }
359+
360+ /**
361+ * @inheritdoc
362+ */
363+ public function getMountsForPath (
364+ string $ path ,
365+ bool $ forChildren ,
366+ array $ mountProviderArgs ,
367+ IStorageFactory $ loader ,
368+ ): array {
369+ if (empty ($ mountProviderArgs )) {
370+ return [];
371+ }
372+
373+ $ limit = -1 ;
374+ $ userId = null ;
375+ $ user = null ;
376+ foreach ($ mountProviderArgs as $ mountProviderArg ) {
377+ if ($ userId === null ) {
378+ $ user = $ mountProviderArg ->mountInfo ->getUser ();
379+ $ userId = $ user ->getUID ();
380+ } elseif ($ userId !== $ mountProviderArg ->mountInfo ->getUser ()->getUID ()) {
381+ throw new \LogicException ('Mounts must belong to the same user! ' );
354382 }
383+ }
384+
385+ if (!$ forChildren ) {
386+ // override path with mount point when fetching without children
387+ $ path = $ mountProviderArgs [0 ]->mountInfo ->getMountPoint ();
388+ }
389+
390+ // remove /uid/files and the trailing slash as the target is stored
391+ // without it
392+ $ path = \rtrim (\substr ($ path , \strlen ('/ ' . $ userId . '/files ' )), '/ ' );
393+
394+ $ shares = $ this ->mergeIterables (
395+ $ this ->shareManager ->getSharedWithByPath ($ userId ,
396+ IShare::TYPE_USER , $ path , $ forChildren , $ limit ),
397+ $ this ->shareManager ->getSharedWithByPath ($ userId ,
398+ IShare::TYPE_GROUP , $ path , $ forChildren , $ limit ),
399+ $ this ->shareManager ->getSharedWithByPath ($ userId ,
400+ IShare::TYPE_CIRCLE , $ path , $ forChildren , $ limit ),
401+ $ this ->shareManager ->getSharedWithByPath ($ userId ,
402+ IShare::TYPE_ROOM , $ path , $ forChildren , $ limit ),
403+ $ this ->shareManager ->getSharedWithByPath ($ userId ,
404+ IShare::TYPE_DECK , $ path , $ forChildren , $ limit ),
405+ $ this ->shareManager ->getSharedWithByPath ($ userId ,
406+ IShare::TYPE_SCIENCEMESH , $ path , $ forChildren , $ limit ),
355407 );
408+
409+ $ shares = $ this ->filterShares ($ shares , $ userId );
410+ $ superShares = $ this ->buildSuperShares ($ shares , $ user );
411+
412+ $ superShares = \array_filter ($ superShares , function (array $ shares ) use ($ mountProviderArgs ) {
413+ /** @var IShare $superShare */
414+ $ superShare = $ shares [0 ];
415+
416+ return array_any ($ mountProviderArgs ,
417+ function (IMountProviderArgs $ mountProviderArg ) use ($ superShare ) {
418+ return $ superShare ->getNodeId () === $ mountProviderArg ->mountInfo ->getRootId ();
419+ });
420+ });
421+
422+ return $ this ->getMountsFromSuperShares ($ userId ,
423+ $ superShares ,
424+ $ loader ,
425+ $ user );
426+ }
427+
428+ /**
429+ * @param iterable ...$iterables
430+ * @return iterable
431+ */
432+ private function mergeIterables (...$ iterables ): iterable {
433+ foreach ($ iterables as $ iterable ) {
434+ foreach ($ iterable as $ value ) {
435+ yield $ value ;
436+ }
437+ }
356438 }
357439}
0 commit comments