1313use OCP \DB \QueryBuilder \IQueryBuilder ;
1414use OCP \Files \Config \ICachedMountInfo ;
1515use OCP \Files \Config \IUserMountCache ;
16+ use OCP \Files \IRootFolder ;
17+ use OCP \Files \NotFoundException ;
1618use OCP \IDBConnection ;
1719use OCP \IUserManager ;
1820use OCP \Migration \IOutput ;
1921use OCP \Migration \IRepairStep ;
20- use OCP \Share \IManager ;
21- use OCP \Share \IProviderFactory ;
2222use OCP \Share \IShare ;
23+ use Psr \Log \LoggerInterface ;
2324
25+ /**
26+ * @psalm-type ShareInfo = array{id: string|int, share_type: string, share_with: string, file_source: string, file_target: string}
27+ */
2428class CleanupShareTarget implements IRepairStep {
2529 /** we only care about shares with a user target,
2630 * since the underling group/deck/talk share doesn't get moved
@@ -34,12 +38,12 @@ class CleanupShareTarget implements IRepairStep {
3438
3539 public function __construct (
3640 private readonly IDBConnection $ connection ,
37- private readonly IManager $ shareManager ,
38- private readonly IProviderFactory $ shareProviderFactory ,
3941 private readonly ShareTargetValidator $ shareTargetValidator ,
4042 private readonly IUserManager $ userManager ,
4143 private readonly SetupManager $ setupManager ,
4244 private readonly IUserMountCache $ userMountCache ,
45+ private readonly IRootFolder $ rootFolder ,
46+ private readonly LoggerInterface $ logger ,
4347 ) {
4448 }
4549
@@ -58,12 +62,13 @@ public function run(IOutput $output) {
5862
5963 $ lastUser = '' ;
6064 $ userMounts = [];
65+ $ userFolder = null ;
6166
6267 foreach ($ this ->getProblemShares () as $ shareInfo ) {
6368 $ recipient = $ this ->userManager ->getExistingUser ($ shareInfo ['share_with ' ]);
64- $ share = $ this -> shareProviderFactory
65- -> getProviderForType (( int ) $ shareInfo [ ' share_type ' ])
66- -> getShareById ( $ shareInfo [ ' id ' ], $ recipient -> getUID ());
69+ if (! $ recipient -> isEnabled ()) {
70+ continue ;
71+ }
6772
6873 // since we ordered the share by user, we can reuse the last data until we get to the next user
6974 if ($ lastUser !== $ recipient ->getUID ()) {
@@ -74,24 +79,39 @@ public function run(IOutput $output) {
7479 $ mounts = $ this ->userMountCache ->getMountsForUser ($ recipient );
7580 $ mountPoints = array_map (fn (ICachedMountInfo $ mount ) => $ mount ->getMountPoint (), $ mounts );
7681 $ userMounts = array_combine ($ mountPoints , $ mounts );
82+ $ userFolder = $ this ->rootFolder ->getUserFolder ($ recipient ->getUID ());
7783 }
7884
79- $ oldTarget = $ share -> getTarget () ;
85+ $ oldTarget = $ shareInfo [ ' file_target ' ] ;
8086 $ newTarget = $ this ->cleanTarget ($ oldTarget );
81- $ share ->setTarget ($ newTarget );
82- $ this ->shareManager ->moveShare ($ share , $ recipient ->getUID ());
83-
84- $ this ->shareTargetValidator ->verifyMountPoint (
85- $ recipient ,
86- $ share ,
87- $ userMounts ,
88- [$ share ],
89- );
87+ $ absoluteNewTarget = $ userFolder ->getFullPath ($ newTarget );
88+ try {
89+ $ targetParentNode = $ this ->rootFolder ->get (dirname ($ absoluteNewTarget ));
90+ } catch (NotFoundException ) {
91+ $ absoluteNewTarget = $ userFolder ->getFullPath (basename ($ newTarget ));
92+ $ targetParentNode = $ userFolder ;
93+ }
9094
91- $ oldMountPoint = "/ {$ recipient ->getUID ()}/files $ oldTarget/ " ;
92- $ newMountPoint = "/ {$ recipient ->getUID ()}/files $ newTarget/ " ;
93- $ userMounts [$ newMountPoint ] = $ userMounts [$ oldMountPoint ];
94- unset($ userMounts [$ oldMountPoint ]);
95+ try {
96+ $ absoluteNewTarget = $ this ->shareTargetValidator ->generateUniqueTarget (
97+ (int )$ shareInfo ['file_source ' ],
98+ $ absoluteNewTarget ,
99+ $ targetParentNode ->getMountPoint (),
100+ $ userMounts ,
101+ );
102+ $ newTarget = $ userFolder ->getRelativePath ($ absoluteNewTarget );
103+
104+ $ this ->moveShare ((string )$ shareInfo ['id ' ], $ newTarget );
105+
106+ $ oldMountPoint = "/ {$ recipient ->getUID ()}/files $ oldTarget/ " ;
107+ $ newMountPoint = "/ {$ recipient ->getUID ()}/files $ newTarget/ " ;
108+ $ userMounts [$ newMountPoint ] = $ userMounts [$ oldMountPoint ];
109+ unset($ userMounts [$ oldMountPoint ]);
110+ } catch (\Exception $ e ) {
111+ $ msg = 'error cleaning up share target: ' . $ e ->getMessage ();
112+ $ this ->logger ->error ($ msg , ['exception ' => $ e , 'app ' => 'files_sharing ' ]);
113+ $ output ->warning ($ msg );
114+ }
95115
96116 $ output ->advance ();
97117 }
@@ -108,19 +128,29 @@ private function countProblemShares(): int {
108128 return (int )$ query ->executeQuery ()->fetchOne ();
109129 }
110130
131+ private function moveShare (string $ id , string $ target ): void {
132+ // since we only process user-specific shares, we can just move them
133+ // without having to check if we need to create a user-specific override
134+ $ query = $ this ->connection ->getQueryBuilder ();
135+ $ query ->update ('share ' )
136+ ->set ('file_target ' , $ query ->createNamedParameter ($ target ))
137+ ->where ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ id )))
138+ ->executeStatement ();
139+ }
140+
111141 /**
112- * @return \Traversable<array{id: string, share_type: string, share_with: string} >
142+ * @return \Traversable<ShareInfo >
113143 */
114144 private function getProblemShares (): \Traversable {
115145 $ query = $ this ->connection ->getQueryBuilder ();
116- $ query ->select ('id ' , 'share_type ' , 'share_with ' )
146+ $ query ->select ('id ' , 'share_type ' , 'share_with ' , ' file_source ' , ' file_target ' )
117147 ->from ('share ' )
118148 ->where ($ query ->expr ()->like ('file_target ' , $ query ->createNamedParameter ('% (_) (_)% ' )))
119149 ->andWhere ($ query ->expr ()->in ('share_type ' , $ query ->createNamedParameter (self ::USER_SHARE_TYPES , IQueryBuilder::PARAM_INT_ARRAY ), IQueryBuilder::PARAM_INT_ARRAY ))
120150 ->orderBy ('share_with ' )
121151 ->addOrderBy ('id ' );
122152 $ result = $ query ->executeQuery ();
123- /** @var \Traversable<array{id: string, share_type: string, share_with: string} > $rows */
153+ /** @var \Traversable<ShareInfo > $rows */
124154 $ rows = $ result ->iterateAssociative ();
125155 return $ rows ;
126156 }
0 commit comments