1414use OCP \Cache \CappedMemoryCache ;
1515use OCP \EventDispatcher \IEventDispatcher ;
1616use OCP \Files \Config \IMountProvider ;
17+ use OCP \Files \Config \IPartialMountProvider ;
1718use OCP \Files \Mount \IMountManager ;
1819use OCP \Files \Mount \IMountPoint ;
1920use OCP \Files \Storage \IStorageFactory ;
2425use OCP \Share \IManager ;
2526use OCP \Share \IShare ;
2627use Psr \Log \LoggerInterface ;
28+ use RecursiveIteratorIterator ;
29+
2730use function count ;
2831
29- class MountProvider implements IMountProvider {
32+ class MountProvider implements IMountProvider, IPartialMountProvider {
3033 /**
3134 * @param IConfig $config
3235 * @param IManager $shareManager
@@ -51,7 +54,7 @@ public function __construct(
5154 */
5255 public function getMountsForUser (IUser $ user , IStorageFactory $ loader ) {
5356 $ userId = $ user ->getUID ();
54- $ shares = array_merge (
57+ $ shares = $ this -> mergeIterables (
5558 $ this ->shareManager ->getSharedWith ($ userId , IShare::TYPE_USER , null , -1 ),
5659 $ this ->shareManager ->getSharedWith ($ userId , IShare::TYPE_GROUP , null , -1 ),
5760 $ this ->shareManager ->getSharedWith ($ userId , IShare::TYPE_CIRCLE , null , -1 ),
@@ -62,17 +65,24 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {
6265 $ shares = $ this ->filterShares ($ shares , $ userId );
6366 $ superShares = $ this ->buildSuperShares ($ shares , $ user );
6467
65- return $ this ->getMountsFromSuperShares ($ userId , $ superShares , $ loader , $ user );
68+ return array_values (
69+ $ this ->getMountsFromSuperShares (
70+ $ userId ,
71+ $ superShares ,
72+ $ loader ,
73+ $ user ,
74+ ),
75+ );
6676 }
6777
6878 /**
6979 * Groups shares by path (nodeId) and target path
7080 *
71- * @param IShare[] $shares
81+ * @param iterable< IShare> $shares
7282 * @return IShare[][] array of grouped shares, each element in the
7383 * array is a group which itself is an array of shares
7484 */
75- private function groupShares (array $ shares ) {
85+ private function groupShares (iterable $ shares ): array {
7686 $ tmp = [];
7787
7888 foreach ($ shares as $ share ) {
@@ -108,11 +118,11 @@ private function groupShares(array $shares) {
108118 * the shares in the group, forming the most permissive combination
109119 * possible.
110120 *
111- * @param IShare[] $allShares
121+ * @param iterable< IShare> $allShares
112122 * @param IUser $user user
113123 * @return list<array{IShare, array<IShare>}> Tuple of [superShare, groupedShares]
114124 */
115- private function buildSuperShares (array $ allShares , IUser $ user ) {
125+ private function buildSuperShares (iterable $ allShares , IUser $ user ): array {
116126 $ result = [];
117127
118128 $ groupedShares = $ this ->groupShares ($ allShares );
@@ -237,8 +247,7 @@ private function adjustTarget(
237247 // null groups which usually appear with group backend
238248 // caching inconsistencies
239249 $ this ->logger ->debug (
240- 'Could not adjust share target for share ' . $ share ->getId (
241- ) . ' to make it consistent: ' . $ e ->getMessage (),
250+ 'Could not adjust share target for share ' . $ share ->getId () . ' to make it consistent: ' . $ e ->getMessage (),
242251 ['app ' => 'files_sharing ' ]
243252 );
244253 }
@@ -248,7 +257,7 @@ private function adjustTarget(
248257 * @param array $superShares
249258 * @param IStorageFactory $loader
250259 * @param IUser $user
251- * @return array
260+ * @return array IMountPoint indexed by mount point
252261 * @throws Exception
253262 */
254263 private function getMountsFromSuperShares (
@@ -261,13 +270,11 @@ private function getMountsFromSuperShares(
261270 $ mounts = [];
262271 $ view = new View ('/ ' . $ userId . '/files ' );
263272 $ ownerViews = [];
264- $ sharingDisabledForUser
265- = $ this ->shareManager ->sharingDisabledForUser ($ userId );
273+ $ sharingDisabledForUser = $ this ->shareManager ->sharingDisabledForUser ($ userId );
266274 /** @var CappedMemoryCache<bool> $folderExistCache */
267275 $ foldersExistCache = new CappedMemoryCache ();
268276
269- $ validShareCache
270- = $ this ->cacheFactory ->createLocal ('share-valid-mountpoint-max ' );
277+ $ validShareCache = $ this ->cacheFactory ->createLocal ('share-valid-mountpoint-max ' );
271278 $ maxValidatedShare = $ validShareCache ->get ($ userId ) ?? 0 ;
272279 $ newMaxValidatedShare = $ maxValidatedShare ;
273280
@@ -312,12 +319,10 @@ private function getMountsFromSuperShares(
312319 $ event = new ShareMountedEvent ($ mount );
313320 $ this ->eventDispatcher ->dispatchTyped ($ event );
314321
315- $ mounts [$ mount ->getMountPoint ()]
316- = $ allMounts [$ mount ->getMountPoint ()] = $ mount ;
322+ $ mounts [$ mount ->getMountPoint ()] = $ allMounts [$ mount ->getMountPoint ()] = $ mount ;
317323 foreach ($ event ->getAdditionalMounts () as $ additionalMount ) {
318- $ allMounts [$ additionalMount ->getMountPoint ()]
319- = $ mounts [$ additionalMount ->getMountPoint ()]
320- = $ additionalMount ;
324+ $ mounts [$ additionalMount ->getMountPoint ()] = $ additionalMount ;
325+ $ allMounts [$ additionalMount ->getMountPoint ()] = $ additionalMount ;
321326 }
322327 } catch (Exception $ e ) {
323328 $ this ->logger ->error (
@@ -333,24 +338,74 @@ private function getMountsFromSuperShares(
333338 $ validShareCache ->set ($ userId , $ newMaxValidatedShare , 24 * 60 * 60 );
334339
335340 // array_filter removes the null values from the array
336- return array_values ( array_filter ($ mounts) );
341+ return array_filter ($ mounts );
337342 }
338343
339344 /**
340345 * Filters out shares owned or shared by the user and ones for which the
341346 * user has no permissions.
342347 *
343- * @param IShare[] $shares
344- * @return IShare[]
348+ * @param iterable< IShare> $shares
349+ * @return iterable< IShare>
345350 */
346- private function filterShares (array $ shares , string $ userId ): array {
347- return array_filter (
348- $ shares ,
349- static function (IShare $ share ) use ($ userId ) {
350- return $ share ->getPermissions () > 0
351- && $ share ->getShareOwner () !== $ userId
352- && $ share ->getSharedBy () !== $ userId ;
351+ private function filterShares (iterable $ shares , string $ userId ): iterable {
352+ foreach ($ shares as $ share ) {
353+ if (
354+ $ share ->getPermissions () > 0
355+ && $ share ->getShareOwner () !== $ userId
356+ && $ share ->getSharedBy () !== $ userId
357+ ) {
358+ yield $ share ;
353359 }
360+ }
361+ }
362+
363+ public function getMountsForPath (
364+ string $ path ,
365+ bool $ forChildren ,
366+ array $ mountProviderArgs ,
367+ IStorageFactory $ loader ,
368+ ): array {
369+ $ limit = -1 ;
370+ $ user = $ mountProviderArgs [0 ]->mountInfo ->getUser ();
371+ $ userId = $ user ->getUID ();
372+
373+ if (!$ forChildren ) {
374+ // override path with mount point when fetching without children
375+ $ path = $ mountProviderArgs [0 ]->mountInfo ->getMountPoint ();
376+ }
377+
378+ // remove /uid/files as the target is stored without
379+ $ path = \substr ($ path , \strlen ('/ ' . $ userId . '/files ' ));
380+ // remove trailing slash
381+ $ path = \rtrim ($ path , '/ ' );
382+
383+ // make sure trailing slash is present when loading children
384+ if ($ forChildren || $ path === '' ) {
385+ $ path .= '/ ' ;
386+ }
387+
388+ $ shares = $ this ->mergeIterables (
389+ $ this ->shareManager ->getSharedWithByPath ($ userId , IShare::TYPE_USER , $ path , $ forChildren , $ limit ),
390+ $ this ->shareManager ->getSharedWithByPath ($ userId , IShare::TYPE_GROUP , $ path , $ forChildren , $ limit ),
391+ $ this ->shareManager ->getSharedWithByPath ($ userId , IShare::TYPE_CIRCLE , $ path , $ forChildren , $ limit ),
392+ $ this ->shareManager ->getSharedWithByPath ($ userId , IShare::TYPE_ROOM , $ path , $ forChildren , $ limit ),
393+ $ this ->shareManager ->getSharedWithByPath ($ userId , IShare::TYPE_DECK , $ path , $ forChildren , $ limit ),
354394 );
395+
396+ $ shares = $ this ->filterShares ($ shares , $ userId );
397+ $ superShares = $ this ->buildSuperShares ($ shares , $ user );
398+
399+ return $ this ->getMountsFromSuperShares ($ userId , $ superShares , $ loader , $ user );
400+ }
401+
402+ /**
403+ * @param iterable ...$iterables
404+ * @return iterable
405+ */
406+ private function mergeIterables (...$ iterables ): iterable {
407+ foreach ($ iterables as $ iterable ) {
408+ yield from $ iterable ;
409+ }
355410 }
356411}
0 commit comments