1111use OC \Files \SetupManager ;
1212use OCA \Files_Sharing \ShareTargetValidator ;
1313use OCP \DB \QueryBuilder \IQueryBuilder ;
14+ use OCP \Files \IRootFolder ;
1415use OCP \Files \Mount \IMountManager ;
1516use OCP \IDBConnection ;
1617use OCP \IUserManager ;
1718use OCP \Migration \IOutput ;
1819use OCP \Migration \IRepairStep ;
19- use OCP \Share \IManager ;
20- use OCP \Share \IProviderFactory ;
2120use OCP \Share \IShare ;
2221
22+ /**
23+ * @psalm-type ShareInfo = array{id: string|int, share_type: string, share_with: string, file_source: string, file_target: string};
24+ */
2325class CleanupShareTarget implements IRepairStep {
2426 /** we only care about shares with a user target,
2527 * since the underling group/deck/talk share doesn't get moved
@@ -33,12 +35,11 @@ class CleanupShareTarget implements IRepairStep {
3335
3436 public function __construct (
3537 private readonly IDBConnection $ connection ,
36- private readonly IManager $ shareManager ,
37- private readonly IProviderFactory $ shareProviderFactory ,
3838 private readonly ShareTargetValidator $ shareTargetValidator ,
3939 private readonly IUserManager $ userManager ,
4040 private readonly SetupManager $ setupManager ,
4141 private readonly IMountManager $ mountManager ,
42+ private readonly IRootFolder $ rootFolder ,
4243 ) {
4344 }
4445
@@ -57,12 +58,10 @@ public function run(IOutput $output) {
5758
5859 $ lastUser = '' ;
5960 $ userMounts = [];
61+ $ userFolder = null ;
6062
6163 foreach ($ this ->getProblemShares () as $ shareInfo ) {
6264 $ recipient = $ this ->userManager ->getExistingUser ($ shareInfo ['share_with ' ]);
63- $ share = $ this ->shareProviderFactory
64- ->getProviderForType ((int )$ shareInfo ['share_type ' ])
65- ->getShareById ($ shareInfo ['id ' ], $ recipient ->getUID ());
6665
6766 // since we ordered the share by user, we can reuse the last data until we get to the next user
6867 if ($ lastUser !== $ recipient ->getUID ()) {
@@ -71,19 +70,23 @@ public function run(IOutput $output) {
7170 $ this ->setupManager ->tearDown ();
7271 $ this ->setupManager ->setupForUser ($ recipient );
7372 $ userMounts = $ this ->mountManager ->getAll ();
73+ $ userFolder = $ this ->rootFolder ->getUserFolder ($ recipient ->getUID ());
7474 }
7575
76- $ oldTarget = $ share -> getTarget () ;
76+ $ oldTarget = $ shareInfo [ ' file_target ' ] ;
7777 $ newTarget = $ this ->cleanTarget ($ oldTarget );
78- $ share -> setTarget ($ newTarget );
79- $ this ->shareManager -> moveShare ( $ share , $ recipient -> getUID ( ));
78+ $ absoluteNewTarget = $ userFolder -> getFullPath ($ newTarget );
79+ $ targetParentNode = $ this ->rootFolder -> get ( dirname ( $ absoluteNewTarget ));
8080
81- $ this ->shareTargetValidator ->verifyMountPoint (
82- $ recipient ,
83- $ share ,
81+ $ absoluteNewTarget = $ this ->shareTargetValidator ->generateUniqueTarget (
82+ $ shareInfo ['file_source ' ],
83+ $ absoluteNewTarget ,
84+ $ targetParentNode ->getMountPoint (),
8485 $ userMounts ,
85- [$ share ],
8686 );
87+ $ newTarget = $ userFolder ->getRelativePath ($ absoluteNewTarget );
88+
89+ $ this ->moveShare ((string )$ shareInfo ['id ' ], $ newTarget );
8790
8891 $ oldMountPoint = "/ {$ recipient ->getUID ()}/files $ oldTarget/ " ;
8992 $ newMountPoint = "/ {$ recipient ->getUID ()}/files $ newTarget/ " ;
@@ -105,12 +108,22 @@ private function countProblemShares(): int {
105108 return (int )$ query ->executeQuery ()->fetchOne ();
106109 }
107110
111+ private function moveShare (string $ id , string $ target ) {
112+ // since we only process user-specific shares, we can just move them
113+ // without having to check if we need to create a user-specific override
114+ $ query = $ this ->connection ->getQueryBuilder ();
115+ $ query ->update ('share ' )
116+ ->set ('file_target ' , $ query ->createNamedParameter ($ target ))
117+ ->where ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ id )))
118+ ->executeStatement ();
119+ }
120+
108121 /**
109- * @return \Traversable<array{id: string, share_type: string, share_with: string} >
122+ * @return \Traversable<ShareInfo >
110123 */
111124 private function getProblemShares (): \Traversable {
112125 $ query = $ this ->connection ->getQueryBuilder ();
113- $ query ->select ('id ' , 'share_type ' , 'share_with ' )
126+ $ query ->select ('id ' , 'share_type ' , 'share_with ' , ' file_source ' , ' file_target ' )
114127 ->from ('share ' )
115128 ->where ($ query ->expr ()->like ('file_target ' , $ query ->createNamedParameter ('% (_) (_)% ' )))
116129 ->andWhere ($ query ->expr ()->in ('share_type ' , $ query ->createNamedParameter (self ::USER_SHARE_TYPES , IQueryBuilder::PARAM_INT_ARRAY ), IQueryBuilder::PARAM_INT_ARRAY ))
0 commit comments