Completed
Push — master ( 453450...6f0537 )
by
unknown
37:16
created
apps/files_sharing/tests/ExpireSharesJobTest.php 1 patch
Indentation   +173 added lines, -173 removed lines patch added patch discarded remove patch
@@ -26,177 +26,177 @@
 block discarded – undo
26 26
 #[\PHPUnit\Framework\Attributes\Group('DB')]
27 27
 class ExpireSharesJobTest extends \Test\TestCase {
28 28
 
29
-	/** @var ExpireSharesJob */
30
-	private $job;
31
-
32
-	/** @var IDBConnection */
33
-	private $connection;
34
-
35
-	/** @var string */
36
-	private $user1;
37
-
38
-	/** @var string */
39
-	private $user2;
40
-
41
-	protected function setUp(): void {
42
-		parent::setUp();
43
-
44
-		$this->connection = Server::get(IDBConnection::class);
45
-		// clear occasional leftover shares from other tests
46
-		$qb = $this->connection->getQueryBuilder();
47
-		$qb->delete('share')->executeStatement();
48
-
49
-		$this->user1 = $this->getUniqueID('user1_');
50
-		$this->user2 = $this->getUniqueID('user2_');
51
-
52
-		$userManager = Server::get(IUserManager::class);
53
-		$userManager->createUser($this->user1, 'longrandompassword');
54
-		$userManager->createUser($this->user2, 'longrandompassword');
55
-
56
-		\OC::registerShareHooks(Server::get(SystemConfig::class));
57
-
58
-		$this->job = new ExpireSharesJob(Server::get(ITimeFactory::class), Server::get(IManager::class), $this->connection);
59
-	}
60
-
61
-	protected function tearDown(): void {
62
-		$qb = $this->connection->getQueryBuilder();
63
-		$qb->delete('share')->executeStatement();
64
-
65
-		$userManager = Server::get(IUserManager::class);
66
-		$user1 = $userManager->get($this->user1);
67
-		if ($user1) {
68
-			$user1->delete();
69
-		}
70
-		$user2 = $userManager->get($this->user2);
71
-		if ($user2) {
72
-			$user2->delete();
73
-		}
74
-
75
-		$this->logout();
76
-
77
-		parent::tearDown();
78
-	}
79
-
80
-	private function getShares() {
81
-		$shares = [];
82
-		$qb = $this->connection->getQueryBuilder();
83
-
84
-		$result = $qb->select('*')
85
-			->from('share')
86
-			->executeQuery();
87
-
88
-		while ($row = $result->fetchAssociative()) {
89
-			$shares[] = $row;
90
-		}
91
-		$result->closeCursor();
92
-		return $shares;
93
-	}
94
-
95
-	public static function dataExpireLinkShare() {
96
-		return [
97
-			[false,   '', false, false],
98
-			[false,   '',  true, false],
99
-			[true, 'P1D', false,  true],
100
-			[true, 'P1D',  true, false],
101
-			[true, 'P1W', false,  true],
102
-			[true, 'P1W',  true, false],
103
-			[true, 'P1M', false,  true],
104
-			[true, 'P1M',  true, false],
105
-			[true, 'P1Y', false,  true],
106
-			[true, 'P1Y',  true, false],
107
-		];
108
-	}
109
-
110
-	/**
111
-	 *
112
-	 * @param bool addExpiration Should we add an expire date
113
-	 * @param string $interval The dateInterval
114
-	 * @param bool $addInterval If true add to the current time if false subtract
115
-	 * @param bool $shouldExpire Should this share be expired
116
-	 */
117
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataExpireLinkShare')]
118
-	public function testExpireLinkShare($addExpiration, $interval, $addInterval, $shouldExpire): void {
119
-		$this->loginAsUser($this->user1);
120
-
121
-		$user1Folder = \OC::$server->getUserFolder($this->user1);
122
-		$testFolder = $user1Folder->newFolder('test');
123
-
124
-		$shareManager = Server::get(\OCP\Share\IManager::class);
125
-		$share = $shareManager->newShare();
126
-
127
-		$share->setNode($testFolder)
128
-			->setShareType(IShare::TYPE_LINK)
129
-			->setPermissions(Constants::PERMISSION_READ)
130
-			->setSharedBy($this->user1);
131
-
132
-		$shareManager->createShare($share);
133
-
134
-		$shares = $this->getShares();
135
-		$this->assertCount(1, $shares);
136
-		reset($shares);
137
-		$share = current($shares);
138
-
139
-		if ($addExpiration) {
140
-			$expire = new \DateTime();
141
-			$expire->setTime(0, 0, 0);
142
-			if ($addInterval) {
143
-				$expire->add(new \DateInterval($interval));
144
-			} else {
145
-				$expire->sub(new \DateInterval($interval));
146
-			}
147
-			$expire = $expire->format('Y-m-d 00:00:00');
148
-
149
-			// Set expiration date to yesterday
150
-			$qb = $this->connection->getQueryBuilder();
151
-			$qb->update('share')
152
-				->set('expiration', $qb->createParameter('expiration'))
153
-				->where($qb->expr()->eq('id', $qb->createParameter('id')))
154
-				->setParameter('id', $share['id'])
155
-				->setParameter('expiration', $expire)
156
-				->executeStatement();
157
-
158
-			$shares = $this->getShares();
159
-			$this->assertCount(1, $shares);
160
-		}
161
-
162
-		$this->logout();
163
-
164
-		$this->job->run([]);
165
-
166
-		$shares = $this->getShares();
167
-
168
-		if ($shouldExpire) {
169
-			$this->assertCount(0, $shares);
170
-		} else {
171
-			$this->assertCount(1, $shares);
172
-		}
173
-	}
174
-
175
-	public function testDoNotExpireOtherShares(): void {
176
-		$this->loginAsUser($this->user1);
177
-
178
-		$user1Folder = \OC::$server->getUserFolder($this->user1);
179
-		$testFolder = $user1Folder->newFolder('test');
180
-
181
-		$shareManager = Server::get(\OCP\Share\IManager::class);
182
-		$share = $shareManager->newShare();
183
-
184
-		$share->setNode($testFolder)
185
-			->setShareType(IShare::TYPE_USER)
186
-			->setPermissions(Constants::PERMISSION_READ)
187
-			->setSharedBy($this->user1)
188
-			->setSharedWith($this->user2);
189
-
190
-		$shareManager->createShare($share);
191
-
192
-		$shares = $this->getShares();
193
-		$this->assertCount(1, $shares);
194
-
195
-		$this->logout();
196
-
197
-		$this->job->run([]);
198
-
199
-		$shares = $this->getShares();
200
-		$this->assertCount(1, $shares);
201
-	}
29
+    /** @var ExpireSharesJob */
30
+    private $job;
31
+
32
+    /** @var IDBConnection */
33
+    private $connection;
34
+
35
+    /** @var string */
36
+    private $user1;
37
+
38
+    /** @var string */
39
+    private $user2;
40
+
41
+    protected function setUp(): void {
42
+        parent::setUp();
43
+
44
+        $this->connection = Server::get(IDBConnection::class);
45
+        // clear occasional leftover shares from other tests
46
+        $qb = $this->connection->getQueryBuilder();
47
+        $qb->delete('share')->executeStatement();
48
+
49
+        $this->user1 = $this->getUniqueID('user1_');
50
+        $this->user2 = $this->getUniqueID('user2_');
51
+
52
+        $userManager = Server::get(IUserManager::class);
53
+        $userManager->createUser($this->user1, 'longrandompassword');
54
+        $userManager->createUser($this->user2, 'longrandompassword');
55
+
56
+        \OC::registerShareHooks(Server::get(SystemConfig::class));
57
+
58
+        $this->job = new ExpireSharesJob(Server::get(ITimeFactory::class), Server::get(IManager::class), $this->connection);
59
+    }
60
+
61
+    protected function tearDown(): void {
62
+        $qb = $this->connection->getQueryBuilder();
63
+        $qb->delete('share')->executeStatement();
64
+
65
+        $userManager = Server::get(IUserManager::class);
66
+        $user1 = $userManager->get($this->user1);
67
+        if ($user1) {
68
+            $user1->delete();
69
+        }
70
+        $user2 = $userManager->get($this->user2);
71
+        if ($user2) {
72
+            $user2->delete();
73
+        }
74
+
75
+        $this->logout();
76
+
77
+        parent::tearDown();
78
+    }
79
+
80
+    private function getShares() {
81
+        $shares = [];
82
+        $qb = $this->connection->getQueryBuilder();
83
+
84
+        $result = $qb->select('*')
85
+            ->from('share')
86
+            ->executeQuery();
87
+
88
+        while ($row = $result->fetchAssociative()) {
89
+            $shares[] = $row;
90
+        }
91
+        $result->closeCursor();
92
+        return $shares;
93
+    }
94
+
95
+    public static function dataExpireLinkShare() {
96
+        return [
97
+            [false,   '', false, false],
98
+            [false,   '',  true, false],
99
+            [true, 'P1D', false,  true],
100
+            [true, 'P1D',  true, false],
101
+            [true, 'P1W', false,  true],
102
+            [true, 'P1W',  true, false],
103
+            [true, 'P1M', false,  true],
104
+            [true, 'P1M',  true, false],
105
+            [true, 'P1Y', false,  true],
106
+            [true, 'P1Y',  true, false],
107
+        ];
108
+    }
109
+
110
+    /**
111
+     *
112
+     * @param bool addExpiration Should we add an expire date
113
+     * @param string $interval The dateInterval
114
+     * @param bool $addInterval If true add to the current time if false subtract
115
+     * @param bool $shouldExpire Should this share be expired
116
+     */
117
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataExpireLinkShare')]
118
+    public function testExpireLinkShare($addExpiration, $interval, $addInterval, $shouldExpire): void {
119
+        $this->loginAsUser($this->user1);
120
+
121
+        $user1Folder = \OC::$server->getUserFolder($this->user1);
122
+        $testFolder = $user1Folder->newFolder('test');
123
+
124
+        $shareManager = Server::get(\OCP\Share\IManager::class);
125
+        $share = $shareManager->newShare();
126
+
127
+        $share->setNode($testFolder)
128
+            ->setShareType(IShare::TYPE_LINK)
129
+            ->setPermissions(Constants::PERMISSION_READ)
130
+            ->setSharedBy($this->user1);
131
+
132
+        $shareManager->createShare($share);
133
+
134
+        $shares = $this->getShares();
135
+        $this->assertCount(1, $shares);
136
+        reset($shares);
137
+        $share = current($shares);
138
+
139
+        if ($addExpiration) {
140
+            $expire = new \DateTime();
141
+            $expire->setTime(0, 0, 0);
142
+            if ($addInterval) {
143
+                $expire->add(new \DateInterval($interval));
144
+            } else {
145
+                $expire->sub(new \DateInterval($interval));
146
+            }
147
+            $expire = $expire->format('Y-m-d 00:00:00');
148
+
149
+            // Set expiration date to yesterday
150
+            $qb = $this->connection->getQueryBuilder();
151
+            $qb->update('share')
152
+                ->set('expiration', $qb->createParameter('expiration'))
153
+                ->where($qb->expr()->eq('id', $qb->createParameter('id')))
154
+                ->setParameter('id', $share['id'])
155
+                ->setParameter('expiration', $expire)
156
+                ->executeStatement();
157
+
158
+            $shares = $this->getShares();
159
+            $this->assertCount(1, $shares);
160
+        }
161
+
162
+        $this->logout();
163
+
164
+        $this->job->run([]);
165
+
166
+        $shares = $this->getShares();
167
+
168
+        if ($shouldExpire) {
169
+            $this->assertCount(0, $shares);
170
+        } else {
171
+            $this->assertCount(1, $shares);
172
+        }
173
+    }
174
+
175
+    public function testDoNotExpireOtherShares(): void {
176
+        $this->loginAsUser($this->user1);
177
+
178
+        $user1Folder = \OC::$server->getUserFolder($this->user1);
179
+        $testFolder = $user1Folder->newFolder('test');
180
+
181
+        $shareManager = Server::get(\OCP\Share\IManager::class);
182
+        $share = $shareManager->newShare();
183
+
184
+        $share->setNode($testFolder)
185
+            ->setShareType(IShare::TYPE_USER)
186
+            ->setPermissions(Constants::PERMISSION_READ)
187
+            ->setSharedBy($this->user1)
188
+            ->setSharedWith($this->user2);
189
+
190
+        $shareManager->createShare($share);
191
+
192
+        $shares = $this->getShares();
193
+        $this->assertCount(1, $shares);
194
+
195
+        $this->logout();
196
+
197
+        $this->job->run([]);
198
+
199
+        $shares = $this->getShares();
200
+        $this->assertCount(1, $shares);
201
+    }
202 202
 }
Please login to merge, or discard this patch.
apps/files_sharing/tests/Migration/SetPasswordColumnTest.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -21,87 +21,87 @@
 block discarded – undo
21 21
 #[\PHPUnit\Framework\Attributes\Group('DB')]
22 22
 class SetPasswordColumnTest extends TestCase {
23 23
 
24
-	/** @var IDBConnection */
25
-	private $connection;
26
-
27
-	/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
28
-	private $config;
29
-
30
-	/** @var SetPasswordColumn */
31
-	private $migration;
32
-
33
-	private $table = 'share';
34
-
35
-	protected function setUp(): void {
36
-		parent::setUp();
37
-
38
-		$this->connection = Server::get(IDBConnection::class);
39
-		$this->config = $this->createMock(IConfig::class);
40
-		$this->migration = new SetPasswordColumn($this->connection, $this->config);
41
-
42
-		$this->cleanDB();
43
-	}
44
-
45
-	protected function tearDown(): void {
46
-		parent::tearDown();
47
-		$this->cleanDB();
48
-	}
49
-
50
-	private function cleanDB() {
51
-		$query = $this->connection->getQueryBuilder();
52
-		$query->delete($this->table)->executeStatement();
53
-	}
54
-
55
-	public function testAddPasswordColumn(): void {
56
-		$this->config->expects($this->once())
57
-			->method('getAppValue')
58
-			->with('files_sharing', 'installed_version', '0.0.0')
59
-			->willReturn('1.3.0');
60
-
61
-		$shareTypes = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_EMAIL, IShare::TYPE_LINK];
62
-
63
-		foreach ($shareTypes as $shareType) {
64
-			for ($i = 0; $i < 5; $i++) {
65
-				$query = $this->connection->getQueryBuilder();
66
-				$query->insert($this->table)
67
-					->values([
68
-						'share_type' => $query->createNamedParameter($shareType),
69
-						'share_with' => $query->createNamedParameter('shareWith'),
70
-						'uid_owner' => $query->createNamedParameter('user' . $i),
71
-						'uid_initiator' => $query->createNamedParameter(null),
72
-						'parent' => $query->createNamedParameter(0),
73
-						'item_type' => $query->createNamedParameter('file'),
74
-						'item_source' => $query->createNamedParameter('2'),
75
-						'item_target' => $query->createNamedParameter('/2'),
76
-						'file_source' => $query->createNamedParameter(2),
77
-						'file_target' => $query->createNamedParameter('/foobar'),
78
-						'permissions' => $query->createNamedParameter(31),
79
-						'stime' => $query->createNamedParameter(time()),
80
-					]);
81
-
82
-				$this->assertSame(1, $query->executeStatement());
83
-			}
84
-		}
85
-
86
-		/** @var IOutput $output */
87
-		$output = $this->createMock(IOutput::class);
88
-		$this->migration->run($output);
89
-
90
-		$query = $this->connection->getQueryBuilder();
91
-		$query->select('*')
92
-			->from('share');
93
-		$result = $query->executeQuery();
94
-		$allShares = $result->fetchAllAssociative();
95
-		$result->closeCursor();
96
-
97
-		foreach ($allShares as $share) {
98
-			if ((int)$share['share_type'] === IShare::TYPE_LINK) {
99
-				$this->assertNull($share['share_with']);
100
-				$this->assertSame('shareWith', $share['password']);
101
-			} else {
102
-				$this->assertSame('shareWith', $share['share_with']);
103
-				$this->assertNull($share['password']);
104
-			}
105
-		}
106
-	}
24
+    /** @var IDBConnection */
25
+    private $connection;
26
+
27
+    /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
28
+    private $config;
29
+
30
+    /** @var SetPasswordColumn */
31
+    private $migration;
32
+
33
+    private $table = 'share';
34
+
35
+    protected function setUp(): void {
36
+        parent::setUp();
37
+
38
+        $this->connection = Server::get(IDBConnection::class);
39
+        $this->config = $this->createMock(IConfig::class);
40
+        $this->migration = new SetPasswordColumn($this->connection, $this->config);
41
+
42
+        $this->cleanDB();
43
+    }
44
+
45
+    protected function tearDown(): void {
46
+        parent::tearDown();
47
+        $this->cleanDB();
48
+    }
49
+
50
+    private function cleanDB() {
51
+        $query = $this->connection->getQueryBuilder();
52
+        $query->delete($this->table)->executeStatement();
53
+    }
54
+
55
+    public function testAddPasswordColumn(): void {
56
+        $this->config->expects($this->once())
57
+            ->method('getAppValue')
58
+            ->with('files_sharing', 'installed_version', '0.0.0')
59
+            ->willReturn('1.3.0');
60
+
61
+        $shareTypes = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_EMAIL, IShare::TYPE_LINK];
62
+
63
+        foreach ($shareTypes as $shareType) {
64
+            for ($i = 0; $i < 5; $i++) {
65
+                $query = $this->connection->getQueryBuilder();
66
+                $query->insert($this->table)
67
+                    ->values([
68
+                        'share_type' => $query->createNamedParameter($shareType),
69
+                        'share_with' => $query->createNamedParameter('shareWith'),
70
+                        'uid_owner' => $query->createNamedParameter('user' . $i),
71
+                        'uid_initiator' => $query->createNamedParameter(null),
72
+                        'parent' => $query->createNamedParameter(0),
73
+                        'item_type' => $query->createNamedParameter('file'),
74
+                        'item_source' => $query->createNamedParameter('2'),
75
+                        'item_target' => $query->createNamedParameter('/2'),
76
+                        'file_source' => $query->createNamedParameter(2),
77
+                        'file_target' => $query->createNamedParameter('/foobar'),
78
+                        'permissions' => $query->createNamedParameter(31),
79
+                        'stime' => $query->createNamedParameter(time()),
80
+                    ]);
81
+
82
+                $this->assertSame(1, $query->executeStatement());
83
+            }
84
+        }
85
+
86
+        /** @var IOutput $output */
87
+        $output = $this->createMock(IOutput::class);
88
+        $this->migration->run($output);
89
+
90
+        $query = $this->connection->getQueryBuilder();
91
+        $query->select('*')
92
+            ->from('share');
93
+        $result = $query->executeQuery();
94
+        $allShares = $result->fetchAllAssociative();
95
+        $result->closeCursor();
96
+
97
+        foreach ($allShares as $share) {
98
+            if ((int)$share['share_type'] === IShare::TYPE_LINK) {
99
+                $this->assertNull($share['share_with']);
100
+                $this->assertSame('shareWith', $share['password']);
101
+            } else {
102
+                $this->assertSame('shareWith', $share['share_with']);
103
+                $this->assertNull($share['password']);
104
+            }
105
+        }
106
+    }
107 107
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/SharesReminderJob.php 2 patches
Indentation   +254 added lines, -254 removed lines patch added patch discarded remove patch
@@ -33,275 +33,275 @@
 block discarded – undo
33 33
  * Send a reminder via email to the sharee(s) if the folder is still empty a predefined time before the expiration date
34 34
  */
35 35
 class SharesReminderJob extends TimedJob {
36
-	private const SECONDS_BEFORE_REMINDER = 24 * 60 * 60;
37
-	private const CHUNK_SIZE = 1000;
38
-	private int $folderMimeTypeId;
36
+    private const SECONDS_BEFORE_REMINDER = 24 * 60 * 60;
37
+    private const CHUNK_SIZE = 1000;
38
+    private int $folderMimeTypeId;
39 39
 
40
-	public function __construct(
41
-		ITimeFactory $time,
42
-		private readonly IDBConnection $db,
43
-		private readonly IManager $shareManager,
44
-		private readonly IUserManager $userManager,
45
-		private readonly LoggerInterface $logger,
46
-		private readonly IURLGenerator $urlGenerator,
47
-		private readonly IFactory $l10nFactory,
48
-		private readonly IMailer $mailer,
49
-		private readonly Defaults $defaults,
50
-		IMimeTypeLoader $mimeTypeLoader,
51
-	) {
52
-		parent::__construct($time);
53
-		$this->setInterval(60 * 60);
54
-		$this->folderMimeTypeId = $mimeTypeLoader->getId(ICacheEntry::DIRECTORY_MIMETYPE);
55
-	}
40
+    public function __construct(
41
+        ITimeFactory $time,
42
+        private readonly IDBConnection $db,
43
+        private readonly IManager $shareManager,
44
+        private readonly IUserManager $userManager,
45
+        private readonly LoggerInterface $logger,
46
+        private readonly IURLGenerator $urlGenerator,
47
+        private readonly IFactory $l10nFactory,
48
+        private readonly IMailer $mailer,
49
+        private readonly Defaults $defaults,
50
+        IMimeTypeLoader $mimeTypeLoader,
51
+    ) {
52
+        parent::__construct($time);
53
+        $this->setInterval(60 * 60);
54
+        $this->folderMimeTypeId = $mimeTypeLoader->getId(ICacheEntry::DIRECTORY_MIMETYPE);
55
+    }
56 56
 
57 57
 
58
-	/**
59
-	 * Makes the background job do its work
60
-	 *
61
-	 * @param array $argument unused argument
62
-	 * @throws Exception if a database error occurs
63
-	 */
64
-	public function run(mixed $argument): void {
65
-		foreach ($this->getShares() as $share) {
66
-			$reminderInfo = $this->prepareReminder($share);
67
-			if ($reminderInfo !== null) {
68
-				$this->sendReminder($reminderInfo);
69
-			}
70
-		}
71
-	}
58
+    /**
59
+     * Makes the background job do its work
60
+     *
61
+     * @param array $argument unused argument
62
+     * @throws Exception if a database error occurs
63
+     */
64
+    public function run(mixed $argument): void {
65
+        foreach ($this->getShares() as $share) {
66
+            $reminderInfo = $this->prepareReminder($share);
67
+            if ($reminderInfo !== null) {
68
+                $this->sendReminder($reminderInfo);
69
+            }
70
+        }
71
+    }
72 72
 
73
-	/**
74
-	 * Finds all shares of empty folders, for which the user has write permissions.
75
-	 * The returned shares are of type user or email only, have expiration dates within the specified time frame
76
-	 * and have not yet received a reminder.
77
-	 *
78
-	 * @return array<IShare>|\Iterator
79
-	 * @throws Exception if a database error occurs
80
-	 */
81
-	private function getShares(): array|\Iterator {
82
-		if ($this->db->getShardDefinition('filecache')) {
83
-			$sharesResult = $this->getSharesDataSharded();
84
-		} else {
85
-			$sharesResult = $this->getSharesData();
86
-		}
87
-		foreach ($sharesResult as $share) {
88
-			if ($share['share_type'] === IShare::TYPE_EMAIL) {
89
-				$id = "ocMailShare:$share[id]";
90
-			} else {
91
-				$id = "ocinternal:$share[id]";
92
-			}
73
+    /**
74
+     * Finds all shares of empty folders, for which the user has write permissions.
75
+     * The returned shares are of type user or email only, have expiration dates within the specified time frame
76
+     * and have not yet received a reminder.
77
+     *
78
+     * @return array<IShare>|\Iterator
79
+     * @throws Exception if a database error occurs
80
+     */
81
+    private function getShares(): array|\Iterator {
82
+        if ($this->db->getShardDefinition('filecache')) {
83
+            $sharesResult = $this->getSharesDataSharded();
84
+        } else {
85
+            $sharesResult = $this->getSharesData();
86
+        }
87
+        foreach ($sharesResult as $share) {
88
+            if ($share['share_type'] === IShare::TYPE_EMAIL) {
89
+                $id = "ocMailShare:$share[id]";
90
+            } else {
91
+                $id = "ocinternal:$share[id]";
92
+            }
93 93
 
94
-			try {
95
-				yield $this->shareManager->getShareById($id);
96
-			} catch (ShareNotFound) {
97
-				$this->logger->error("Share with ID $id not found.");
98
-			}
99
-		}
100
-	}
94
+            try {
95
+                yield $this->shareManager->getShareById($id);
96
+            } catch (ShareNotFound) {
97
+                $this->logger->error("Share with ID $id not found.");
98
+            }
99
+        }
100
+    }
101 101
 
102
-	/**
103
-	 * @return list<array{id: int, share_type: int}>
104
-	 */
105
-	private function getSharesData(): array {
106
-		$minDate = new \DateTime();
107
-		$maxDate = new \DateTime();
108
-		$maxDate->setTimestamp($maxDate->getTimestamp() + self::SECONDS_BEFORE_REMINDER);
102
+    /**
103
+     * @return list<array{id: int, share_type: int}>
104
+     */
105
+    private function getSharesData(): array {
106
+        $minDate = new \DateTime();
107
+        $maxDate = new \DateTime();
108
+        $maxDate->setTimestamp($maxDate->getTimestamp() + self::SECONDS_BEFORE_REMINDER);
109 109
 
110
-		$qb = $this->db->getQueryBuilder();
111
-		$qb->select('s.id', 's.share_type')
112
-			->from('share', 's')
113
-			->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('f.parent', 's.file_source'))
114
-			->where(
115
-				$qb->expr()->andX(
116
-					$qb->expr()->orX(
117
-						$qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_USER)),
118
-						$qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_EMAIL))
119
-					),
120
-					$qb->expr()->eq('s.item_type', $qb->expr()->literal('folder')),
121
-					$qb->expr()->gte('s.expiration', $qb->createNamedParameter($minDate, IQueryBuilder::PARAM_DATE)),
122
-					$qb->expr()->lte('s.expiration', $qb->createNamedParameter($maxDate, IQueryBuilder::PARAM_DATE)),
123
-					$qb->expr()->eq('s.reminder_sent', $qb->createNamedParameter(
124
-						false, IQueryBuilder::PARAM_BOOL
125
-					)),
126
-					$qb->expr()->eq(
127
-						$qb->expr()->bitwiseAnd('s.permissions', Constants::PERMISSION_CREATE),
128
-						$qb->createNamedParameter(Constants::PERMISSION_CREATE, IQueryBuilder::PARAM_INT)
129
-					),
130
-					$qb->expr()->isNull('f.fileid')
131
-				)
132
-			)
133
-			->setMaxResults(SharesReminderJob::CHUNK_SIZE);
110
+        $qb = $this->db->getQueryBuilder();
111
+        $qb->select('s.id', 's.share_type')
112
+            ->from('share', 's')
113
+            ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('f.parent', 's.file_source'))
114
+            ->where(
115
+                $qb->expr()->andX(
116
+                    $qb->expr()->orX(
117
+                        $qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_USER)),
118
+                        $qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_EMAIL))
119
+                    ),
120
+                    $qb->expr()->eq('s.item_type', $qb->expr()->literal('folder')),
121
+                    $qb->expr()->gte('s.expiration', $qb->createNamedParameter($minDate, IQueryBuilder::PARAM_DATE)),
122
+                    $qb->expr()->lte('s.expiration', $qb->createNamedParameter($maxDate, IQueryBuilder::PARAM_DATE)),
123
+                    $qb->expr()->eq('s.reminder_sent', $qb->createNamedParameter(
124
+                        false, IQueryBuilder::PARAM_BOOL
125
+                    )),
126
+                    $qb->expr()->eq(
127
+                        $qb->expr()->bitwiseAnd('s.permissions', Constants::PERMISSION_CREATE),
128
+                        $qb->createNamedParameter(Constants::PERMISSION_CREATE, IQueryBuilder::PARAM_INT)
129
+                    ),
130
+                    $qb->expr()->isNull('f.fileid')
131
+                )
132
+            )
133
+            ->setMaxResults(SharesReminderJob::CHUNK_SIZE);
134 134
 
135
-		$shares = $qb->executeQuery()->fetchAllAssociative();
136
-		return array_map(fn ($share): array => [
137
-			'id' => (int)$share['id'],
138
-			'share_type' => (int)$share['share_type'],
139
-		], $shares);
140
-	}
135
+        $shares = $qb->executeQuery()->fetchAllAssociative();
136
+        return array_map(fn ($share): array => [
137
+            'id' => (int)$share['id'],
138
+            'share_type' => (int)$share['share_type'],
139
+        ], $shares);
140
+    }
141 141
 
142
-	/**
143
-	 * Sharding compatible version of getSharesData
144
-	 *
145
-	 * @return list<array{id: int, share_type: int, file_source: int}>
146
-	 */
147
-	private function getSharesDataSharded(): array|\Iterator {
148
-		$minDate = new \DateTime();
149
-		$maxDate = new \DateTime();
150
-		$maxDate->setTimestamp($maxDate->getTimestamp() + self::SECONDS_BEFORE_REMINDER);
142
+    /**
143
+     * Sharding compatible version of getSharesData
144
+     *
145
+     * @return list<array{id: int, share_type: int, file_source: int}>
146
+     */
147
+    private function getSharesDataSharded(): array|\Iterator {
148
+        $minDate = new \DateTime();
149
+        $maxDate = new \DateTime();
150
+        $maxDate->setTimestamp($maxDate->getTimestamp() + self::SECONDS_BEFORE_REMINDER);
151 151
 
152
-		$qb = $this->db->getQueryBuilder();
153
-		$qb->select('s.id', 's.share_type', 's.file_source')
154
-			->from('share', 's')
155
-			->where(
156
-				$qb->expr()->andX(
157
-					$qb->expr()->orX(
158
-						$qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_USER)),
159
-						$qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_EMAIL))
160
-					),
161
-					$qb->expr()->eq('s.item_type', $qb->expr()->literal('folder')),
162
-					$qb->expr()->gte('s.expiration', $qb->createNamedParameter($minDate, IQueryBuilder::PARAM_DATE)),
163
-					$qb->expr()->lte('s.expiration', $qb->createNamedParameter($maxDate, IQueryBuilder::PARAM_DATE)),
164
-					$qb->expr()->eq('s.reminder_sent', $qb->createNamedParameter(
165
-						false, IQueryBuilder::PARAM_BOOL
166
-					)),
167
-					$qb->expr()->eq(
168
-						$qb->expr()->bitwiseAnd('s.permissions', Constants::PERMISSION_CREATE),
169
-						$qb->createNamedParameter(Constants::PERMISSION_CREATE, IQueryBuilder::PARAM_INT)
170
-					),
171
-				)
172
-			);
152
+        $qb = $this->db->getQueryBuilder();
153
+        $qb->select('s.id', 's.share_type', 's.file_source')
154
+            ->from('share', 's')
155
+            ->where(
156
+                $qb->expr()->andX(
157
+                    $qb->expr()->orX(
158
+                        $qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_USER)),
159
+                        $qb->expr()->eq('s.share_type', $qb->expr()->literal(IShare::TYPE_EMAIL))
160
+                    ),
161
+                    $qb->expr()->eq('s.item_type', $qb->expr()->literal('folder')),
162
+                    $qb->expr()->gte('s.expiration', $qb->createNamedParameter($minDate, IQueryBuilder::PARAM_DATE)),
163
+                    $qb->expr()->lte('s.expiration', $qb->createNamedParameter($maxDate, IQueryBuilder::PARAM_DATE)),
164
+                    $qb->expr()->eq('s.reminder_sent', $qb->createNamedParameter(
165
+                        false, IQueryBuilder::PARAM_BOOL
166
+                    )),
167
+                    $qb->expr()->eq(
168
+                        $qb->expr()->bitwiseAnd('s.permissions', Constants::PERMISSION_CREATE),
169
+                        $qb->createNamedParameter(Constants::PERMISSION_CREATE, IQueryBuilder::PARAM_INT)
170
+                    ),
171
+                )
172
+            );
173 173
 
174
-		$shares = $qb->executeQuery()->fetchAllAssociative();
175
-		$shares = array_map(fn ($share): array => [
176
-			'id' => (int)$share['id'],
177
-			'share_type' => (int)$share['share_type'],
178
-			'file_source' => (int)$share['file_source'],
179
-		], $shares);
180
-		return $this->filterSharesWithEmptyFolders($shares, self::CHUNK_SIZE);
181
-	}
174
+        $shares = $qb->executeQuery()->fetchAllAssociative();
175
+        $shares = array_map(fn ($share): array => [
176
+            'id' => (int)$share['id'],
177
+            'share_type' => (int)$share['share_type'],
178
+            'file_source' => (int)$share['file_source'],
179
+        ], $shares);
180
+        return $this->filterSharesWithEmptyFolders($shares, self::CHUNK_SIZE);
181
+    }
182 182
 
183
-	/**
184
-	 * Check which of the supplied file ids is an empty folder until there are `$maxResults` folders
185
-	 * @param list<array{id: int, share_type: int, file_source: int}> $shares
186
-	 * @return list<array{id: int, share_type: int, file_source: int}>
187
-	 */
188
-	private function filterSharesWithEmptyFolders(array $shares, int $maxResults): array {
189
-		$query = $this->db->getQueryBuilder();
190
-		$query->select('fileid')
191
-			->from('filecache')
192
-			->where($query->expr()->eq('size', $query->createNamedParameter(0), IQueryBuilder::PARAM_INT_ARRAY))
193
-			->andWhere($query->expr()->eq('mimetype', $query->createNamedParameter($this->folderMimeTypeId, IQueryBuilder::PARAM_INT)))
194
-			->andWhere($query->expr()->in('fileid', $query->createParameter('fileids')));
195
-		$chunks = array_chunk($shares, SharesReminderJob::CHUNK_SIZE);
196
-		$results = [];
197
-		foreach ($chunks as $chunk) {
198
-			$chunkFileIds = array_map(fn ($share): int => $share['file_source'], $chunk);
199
-			$chunkByFileId = array_combine($chunkFileIds, $chunk);
200
-			$query->setParameter('fileids', $chunkFileIds, IQueryBuilder::PARAM_INT_ARRAY);
201
-			$chunkResults = $query->executeQuery()->fetchFirstColumn();
202
-			foreach ($chunkResults as $folderId) {
203
-				$results[] = $chunkByFileId[$folderId];
204
-			}
205
-			if (count($results) >= $maxResults) {
206
-				break;
207
-			}
208
-		}
209
-		return $results;
210
-	}
183
+    /**
184
+     * Check which of the supplied file ids is an empty folder until there are `$maxResults` folders
185
+     * @param list<array{id: int, share_type: int, file_source: int}> $shares
186
+     * @return list<array{id: int, share_type: int, file_source: int}>
187
+     */
188
+    private function filterSharesWithEmptyFolders(array $shares, int $maxResults): array {
189
+        $query = $this->db->getQueryBuilder();
190
+        $query->select('fileid')
191
+            ->from('filecache')
192
+            ->where($query->expr()->eq('size', $query->createNamedParameter(0), IQueryBuilder::PARAM_INT_ARRAY))
193
+            ->andWhere($query->expr()->eq('mimetype', $query->createNamedParameter($this->folderMimeTypeId, IQueryBuilder::PARAM_INT)))
194
+            ->andWhere($query->expr()->in('fileid', $query->createParameter('fileids')));
195
+        $chunks = array_chunk($shares, SharesReminderJob::CHUNK_SIZE);
196
+        $results = [];
197
+        foreach ($chunks as $chunk) {
198
+            $chunkFileIds = array_map(fn ($share): int => $share['file_source'], $chunk);
199
+            $chunkByFileId = array_combine($chunkFileIds, $chunk);
200
+            $query->setParameter('fileids', $chunkFileIds, IQueryBuilder::PARAM_INT_ARRAY);
201
+            $chunkResults = $query->executeQuery()->fetchFirstColumn();
202
+            foreach ($chunkResults as $folderId) {
203
+                $results[] = $chunkByFileId[$folderId];
204
+            }
205
+            if (count($results) >= $maxResults) {
206
+                break;
207
+            }
208
+        }
209
+        return $results;
210
+    }
211 211
 
212
-	/**
213
-	 * Retrieves and returns all the necessary data before sending a reminder.
214
-	 * It also updates the reminder sent flag for the affected shares (to avoid multiple reminders).
215
-	 *
216
-	 * @param IShare $share Share that was obtained with {@link getShares}
217
-	 * @return array|null Info needed to send a reminder
218
-	 */
219
-	private function prepareReminder(IShare $share): ?array {
220
-		$sharedWith = $share->getSharedWith();
221
-		$reminderInfo = [];
222
-		if ($share->getShareType() == IShare::TYPE_USER) {
223
-			$user = $this->userManager->get($sharedWith);
224
-			if ($user === null) {
225
-				return null;
226
-			}
227
-			$reminderInfo['email'] = $user->getEMailAddress();
228
-			$reminderInfo['userLang'] = $this->l10nFactory->getUserLanguage($user);
229
-			$reminderInfo['folderLink'] = $this->urlGenerator->linkToRouteAbsolute('files.view.index', [
230
-				'dir' => $share->getTarget()
231
-			]);
232
-		} else {
233
-			$reminderInfo['email'] = $sharedWith;
234
-			$reminderInfo['folderLink'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', [
235
-				'token' => $share->getToken()
236
-			]);
237
-		}
238
-		if (empty($reminderInfo['email'])) {
239
-			return null;
240
-		}
212
+    /**
213
+     * Retrieves and returns all the necessary data before sending a reminder.
214
+     * It also updates the reminder sent flag for the affected shares (to avoid multiple reminders).
215
+     *
216
+     * @param IShare $share Share that was obtained with {@link getShares}
217
+     * @return array|null Info needed to send a reminder
218
+     */
219
+    private function prepareReminder(IShare $share): ?array {
220
+        $sharedWith = $share->getSharedWith();
221
+        $reminderInfo = [];
222
+        if ($share->getShareType() == IShare::TYPE_USER) {
223
+            $user = $this->userManager->get($sharedWith);
224
+            if ($user === null) {
225
+                return null;
226
+            }
227
+            $reminderInfo['email'] = $user->getEMailAddress();
228
+            $reminderInfo['userLang'] = $this->l10nFactory->getUserLanguage($user);
229
+            $reminderInfo['folderLink'] = $this->urlGenerator->linkToRouteAbsolute('files.view.index', [
230
+                'dir' => $share->getTarget()
231
+            ]);
232
+        } else {
233
+            $reminderInfo['email'] = $sharedWith;
234
+            $reminderInfo['folderLink'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', [
235
+                'token' => $share->getToken()
236
+            ]);
237
+        }
238
+        if (empty($reminderInfo['email'])) {
239
+            return null;
240
+        }
241 241
 
242
-		try {
243
-			$reminderInfo['folderName'] = $share->getNode()->getName();
244
-		} catch (NotFoundException) {
245
-			$id = $share->getFullId();
246
-			$this->logger->error("File by share ID $id not found.");
247
-		}
248
-		$share->setReminderSent(true);
249
-		$this->shareManager->updateShare($share);
250
-		return $reminderInfo;
251
-	}
242
+        try {
243
+            $reminderInfo['folderName'] = $share->getNode()->getName();
244
+        } catch (NotFoundException) {
245
+            $id = $share->getFullId();
246
+            $this->logger->error("File by share ID $id not found.");
247
+        }
248
+        $share->setReminderSent(true);
249
+        $this->shareManager->updateShare($share);
250
+        return $reminderInfo;
251
+    }
252 252
 
253
-	/**
254
-	 * This method accepts data obtained by {@link prepareReminder} and sends reminder email.
255
-	 *
256
-	 * @param array $reminderInfo
257
-	 * @return void
258
-	 */
259
-	private function sendReminder(array $reminderInfo): void {
260
-		$instanceName = $this->defaults->getName();
261
-		$from = [Util::getDefaultEmailAddress($instanceName) => $instanceName];
262
-		$l = $this->l10nFactory->get('files_sharing', $reminderInfo['userLang'] ?? null);
263
-		$emailTemplate = $this->generateEMailTemplate($l, [
264
-			'link' => $reminderInfo['folderLink'], 'name' => $reminderInfo['folderName']
265
-		]);
253
+    /**
254
+     * This method accepts data obtained by {@link prepareReminder} and sends reminder email.
255
+     *
256
+     * @param array $reminderInfo
257
+     * @return void
258
+     */
259
+    private function sendReminder(array $reminderInfo): void {
260
+        $instanceName = $this->defaults->getName();
261
+        $from = [Util::getDefaultEmailAddress($instanceName) => $instanceName];
262
+        $l = $this->l10nFactory->get('files_sharing', $reminderInfo['userLang'] ?? null);
263
+        $emailTemplate = $this->generateEMailTemplate($l, [
264
+            'link' => $reminderInfo['folderLink'], 'name' => $reminderInfo['folderName']
265
+        ]);
266 266
 
267
-		$message = $this->mailer->createMessage();
268
-		$message->setFrom($from);
269
-		$message->setTo([$reminderInfo['email']]);
270
-		$message->useTemplate($emailTemplate);
271
-		$errorText = "Sending email with share reminder to $reminderInfo[email] failed.";
272
-		try {
273
-			$failedRecipients = $this->mailer->send($message);
274
-			if (count($failedRecipients) > 0) {
275
-				$this->logger->error($errorText);
276
-			}
277
-		} catch (\Exception) {
278
-			$this->logger->error($errorText);
279
-		}
280
-	}
267
+        $message = $this->mailer->createMessage();
268
+        $message->setFrom($from);
269
+        $message->setTo([$reminderInfo['email']]);
270
+        $message->useTemplate($emailTemplate);
271
+        $errorText = "Sending email with share reminder to $reminderInfo[email] failed.";
272
+        try {
273
+            $failedRecipients = $this->mailer->send($message);
274
+            if (count($failedRecipients) > 0) {
275
+                $this->logger->error($errorText);
276
+            }
277
+        } catch (\Exception) {
278
+            $this->logger->error($errorText);
279
+        }
280
+    }
281 281
 
282
-	/**
283
-	 * Returns the reminder email template
284
-	 *
285
-	 * @param IL10N $l
286
-	 * @param array $folder Folder the user should be reminded of
287
-	 * @return IEMailTemplate
288
-	 */
289
-	private function generateEMailTemplate(IL10N $l, array $folder): IEMailTemplate {
290
-		$emailTemplate = $this->mailer->createEMailTemplate('files_sharing.SharesReminder', [
291
-			'folder' => $folder,
292
-		]);
293
-		$emailTemplate->addHeader();
294
-		$emailTemplate->setSubject(
295
-			$l->t('Remember to upload the files to %s', [$folder['name']])
296
-		);
297
-		$emailTemplate->addBodyText($l->t(
298
-			'We would like to kindly remind you that you have not yet uploaded any files to the shared folder.'
299
-		));
300
-		$emailTemplate->addBodyButton(
301
-			$l->t('Open "%s"', [$folder['name']]),
302
-			$folder['link']
303
-		);
304
-		$emailTemplate->addFooter();
305
-		return $emailTemplate;
306
-	}
282
+    /**
283
+     * Returns the reminder email template
284
+     *
285
+     * @param IL10N $l
286
+     * @param array $folder Folder the user should be reminded of
287
+     * @return IEMailTemplate
288
+     */
289
+    private function generateEMailTemplate(IL10N $l, array $folder): IEMailTemplate {
290
+        $emailTemplate = $this->mailer->createEMailTemplate('files_sharing.SharesReminder', [
291
+            'folder' => $folder,
292
+        ]);
293
+        $emailTemplate->addHeader();
294
+        $emailTemplate->setSubject(
295
+            $l->t('Remember to upload the files to %s', [$folder['name']])
296
+        );
297
+        $emailTemplate->addBodyText($l->t(
298
+            'We would like to kindly remind you that you have not yet uploaded any files to the shared folder.'
299
+        ));
300
+        $emailTemplate->addBodyButton(
301
+            $l->t('Open "%s"', [$folder['name']]),
302
+            $folder['link']
303
+        );
304
+        $emailTemplate->addFooter();
305
+        return $emailTemplate;
306
+    }
307 307
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
 	 * @return array<IShare>|\Iterator
79 79
 	 * @throws Exception if a database error occurs
80 80
 	 */
81
-	private function getShares(): array|\Iterator {
81
+	private function getShares(): array | \Iterator {
82 82
 		if ($this->db->getShardDefinition('filecache')) {
83 83
 			$sharesResult = $this->getSharesDataSharded();
84 84
 		} else {
@@ -134,8 +134,8 @@  discard block
 block discarded – undo
134 134
 
135 135
 		$shares = $qb->executeQuery()->fetchAllAssociative();
136 136
 		return array_map(fn ($share): array => [
137
-			'id' => (int)$share['id'],
138
-			'share_type' => (int)$share['share_type'],
137
+			'id' => (int) $share['id'],
138
+			'share_type' => (int) $share['share_type'],
139 139
 		], $shares);
140 140
 	}
141 141
 
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
 	 *
145 145
 	 * @return list<array{id: int, share_type: int, file_source: int}>
146 146
 	 */
147
-	private function getSharesDataSharded(): array|\Iterator {
147
+	private function getSharesDataSharded(): array | \Iterator {
148 148
 		$minDate = new \DateTime();
149 149
 		$maxDate = new \DateTime();
150 150
 		$maxDate->setTimestamp($maxDate->getTimestamp() + self::SECONDS_BEFORE_REMINDER);
@@ -173,9 +173,9 @@  discard block
 block discarded – undo
173 173
 
174 174
 		$shares = $qb->executeQuery()->fetchAllAssociative();
175 175
 		$shares = array_map(fn ($share): array => [
176
-			'id' => (int)$share['id'],
177
-			'share_type' => (int)$share['share_type'],
178
-			'file_source' => (int)$share['file_source'],
176
+			'id' => (int) $share['id'],
177
+			'share_type' => (int) $share['share_type'],
178
+			'file_source' => (int) $share['file_source'],
179 179
 		], $shares);
180 180
 		return $this->filterSharesWithEmptyFolders($shares, self::CHUNK_SIZE);
181 181
 	}
Please login to merge, or discard this patch.
apps/files_sharing/lib/OrphanHelper.php 2 patches
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -15,88 +15,88 @@
 block discarded – undo
15 15
 use OCP\IDBConnection;
16 16
 
17 17
 class OrphanHelper {
18
-	public function __construct(
19
-		private IDBConnection $connection,
20
-		private IRootFolder $rootFolder,
21
-		private IUserMountCache $userMountCache,
22
-	) {
23
-	}
18
+    public function __construct(
19
+        private IDBConnection $connection,
20
+        private IRootFolder $rootFolder,
21
+        private IUserMountCache $userMountCache,
22
+    ) {
23
+    }
24 24
 
25
-	public function isShareValid(string $owner, int $fileId): bool {
26
-		try {
27
-			$userFolder = $this->rootFolder->getUserFolder($owner);
28
-		} catch (NoUserException $e) {
29
-			return false;
30
-		}
31
-		$node = $userFolder->getFirstNodeById($fileId);
32
-		return $node !== null;
33
-	}
25
+    public function isShareValid(string $owner, int $fileId): bool {
26
+        try {
27
+            $userFolder = $this->rootFolder->getUserFolder($owner);
28
+        } catch (NoUserException $e) {
29
+            return false;
30
+        }
31
+        $node = $userFolder->getFirstNodeById($fileId);
32
+        return $node !== null;
33
+    }
34 34
 
35
-	/**
36
-	 * @param int[] $ids
37
-	 * @return void
38
-	 */
39
-	public function deleteShares(array $ids): void {
40
-		$query = $this->connection->getQueryBuilder();
41
-		$query->delete('share')
42
-			->where($query->expr()->in('id', $query->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
43
-		$query->executeStatement();
44
-	}
35
+    /**
36
+     * @param int[] $ids
37
+     * @return void
38
+     */
39
+    public function deleteShares(array $ids): void {
40
+        $query = $this->connection->getQueryBuilder();
41
+        $query->delete('share')
42
+            ->where($query->expr()->in('id', $query->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
43
+        $query->executeStatement();
44
+    }
45 45
 
46
-	public function fileExists(int $fileId): bool {
47
-		$query = $this->connection->getQueryBuilder();
48
-		$query->select('fileid')
49
-			->from('filecache')
50
-			->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
51
-		return $query->executeQuery()->fetchOne() !== false;
52
-	}
46
+    public function fileExists(int $fileId): bool {
47
+        $query = $this->connection->getQueryBuilder();
48
+        $query->select('fileid')
49
+            ->from('filecache')
50
+            ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
51
+        return $query->executeQuery()->fetchOne() !== false;
52
+    }
53 53
 
54
-	/**
55
-	 * @return \Traversable<int, array{id: int, owner: string, fileid: int, target: string}>
56
-	 */
57
-	public function getAllShares(?string $owner = null, ?string $with = null) {
58
-		$query = $this->connection->getQueryBuilder();
59
-		$query->select('id', 'file_source', 'uid_owner', 'file_target')
60
-			->from('share')
61
-			->where($query->expr()->in('item_type', $query->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
54
+    /**
55
+     * @return \Traversable<int, array{id: int, owner: string, fileid: int, target: string}>
56
+     */
57
+    public function getAllShares(?string $owner = null, ?string $with = null) {
58
+        $query = $this->connection->getQueryBuilder();
59
+        $query->select('id', 'file_source', 'uid_owner', 'file_target')
60
+            ->from('share')
61
+            ->where($query->expr()->in('item_type', $query->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
62 62
 
63
-		if ($owner !== null) {
64
-			$query->andWhere($query->expr()->eq('uid_owner', $query->createNamedParameter($owner)));
65
-		}
66
-		if ($with !== null) {
67
-			$query->andWhere($query->expr()->eq('share_with', $query->createNamedParameter($with)));
68
-		}
63
+        if ($owner !== null) {
64
+            $query->andWhere($query->expr()->eq('uid_owner', $query->createNamedParameter($owner)));
65
+        }
66
+        if ($with !== null) {
67
+            $query->andWhere($query->expr()->eq('share_with', $query->createNamedParameter($with)));
68
+        }
69 69
 
70
-		$result = $query->executeQuery();
71
-		while ($row = $result->fetchAssociative()) {
72
-			yield [
73
-				'id' => (int)$row['id'],
74
-				'owner' => (string)$row['uid_owner'],
75
-				'fileid' => (int)$row['file_source'],
76
-				'target' => (string)$row['file_target'],
77
-			];
78
-		}
79
-	}
70
+        $result = $query->executeQuery();
71
+        while ($row = $result->fetchAssociative()) {
72
+            yield [
73
+                'id' => (int)$row['id'],
74
+                'owner' => (string)$row['uid_owner'],
75
+                'fileid' => (int)$row['file_source'],
76
+                'target' => (string)$row['file_target'],
77
+            ];
78
+        }
79
+    }
80 80
 
81
-	public function findOwner(int $fileId): ?string {
82
-		$mounts = $this->userMountCache->getMountsForFileId($fileId);
83
-		if (!$mounts) {
84
-			return null;
85
-		}
86
-		foreach ($mounts as $mount) {
87
-			$userHomeMountPoint = '/' . $mount->getUser()->getUID() . '/';
88
-			if ($mount->getMountPoint() === $userHomeMountPoint) {
89
-				return $mount->getUser()->getUID();
90
-			}
91
-		}
92
-		return null;
93
-	}
81
+    public function findOwner(int $fileId): ?string {
82
+        $mounts = $this->userMountCache->getMountsForFileId($fileId);
83
+        if (!$mounts) {
84
+            return null;
85
+        }
86
+        foreach ($mounts as $mount) {
87
+            $userHomeMountPoint = '/' . $mount->getUser()->getUID() . '/';
88
+            if ($mount->getMountPoint() === $userHomeMountPoint) {
89
+                return $mount->getUser()->getUID();
90
+            }
91
+        }
92
+        return null;
93
+    }
94 94
 
95
-	public function updateShareOwner(int $shareId, string $owner): void {
96
-		$query = $this->connection->getQueryBuilder();
97
-		$query->update('share')
98
-			->set('uid_owner', $query->createNamedParameter($owner))
99
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId, IQueryBuilder::PARAM_INT)));
100
-		$query->executeStatement();
101
-	}
95
+    public function updateShareOwner(int $shareId, string $owner): void {
96
+        $query = $this->connection->getQueryBuilder();
97
+        $query->update('share')
98
+            ->set('uid_owner', $query->createNamedParameter($owner))
99
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId, IQueryBuilder::PARAM_INT)));
100
+        $query->executeStatement();
101
+    }
102 102
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -70,10 +70,10 @@  discard block
 block discarded – undo
70 70
 		$result = $query->executeQuery();
71 71
 		while ($row = $result->fetchAssociative()) {
72 72
 			yield [
73
-				'id' => (int)$row['id'],
74
-				'owner' => (string)$row['uid_owner'],
75
-				'fileid' => (int)$row['file_source'],
76
-				'target' => (string)$row['file_target'],
73
+				'id' => (int) $row['id'],
74
+				'owner' => (string) $row['uid_owner'],
75
+				'fileid' => (int) $row['file_source'],
76
+				'target' => (string) $row['file_target'],
77 77
 			];
78 78
 		}
79 79
 	}
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
 			return null;
85 85
 		}
86 86
 		foreach ($mounts as $mount) {
87
-			$userHomeMountPoint = '/' . $mount->getUser()->getUID() . '/';
87
+			$userHomeMountPoint = '/'.$mount->getUser()->getUID().'/';
88 88
 			if ($mount->getMountPoint() === $userHomeMountPoint) {
89 89
 				return $mount->getUser()->getUID();
90 90
 			}
Please login to merge, or discard this patch.
apps/files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -18,33 +18,33 @@
 block discarded – undo
18 18
 
19 19
 class FederatedSharesDiscoverJob extends TimedJob {
20 20
 
21
-	public function __construct(
22
-		ITimeFactory $time,
23
-		private IDBConnection $connection,
24
-		private IDiscoveryService $discoveryService,
25
-		private IOCMDiscoveryService $ocmDiscoveryService,
26
-		private LoggerInterface $logger,
27
-	) {
28
-		parent::__construct($time);
29
-		$this->setInterval(24 * 60 * 60);
30
-		$this->setTimeSensitivity(self::TIME_INSENSITIVE);
31
-	}
32
-
33
-	public function run($argument) {
34
-		$qb = $this->connection->getQueryBuilder();
35
-
36
-		$qb->selectDistinct('remote')
37
-			->from('share_external');
38
-
39
-		$result = $qb->executeQuery();
40
-		while ($row = $result->fetchAssociative()) {
41
-			$this->discoveryService->discover($row['remote'], 'FEDERATED_SHARING', true);
42
-			try {
43
-				$this->ocmDiscoveryService->discover($row['remote'], true);
44
-			} catch (OCMProviderException $e) {
45
-				$this->logger->info('exception while running files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob', ['exception' => $e]);
46
-			}
47
-		}
48
-		$result->closeCursor();
49
-	}
21
+    public function __construct(
22
+        ITimeFactory $time,
23
+        private IDBConnection $connection,
24
+        private IDiscoveryService $discoveryService,
25
+        private IOCMDiscoveryService $ocmDiscoveryService,
26
+        private LoggerInterface $logger,
27
+    ) {
28
+        parent::__construct($time);
29
+        $this->setInterval(24 * 60 * 60);
30
+        $this->setTimeSensitivity(self::TIME_INSENSITIVE);
31
+    }
32
+
33
+    public function run($argument) {
34
+        $qb = $this->connection->getQueryBuilder();
35
+
36
+        $qb->selectDistinct('remote')
37
+            ->from('share_external');
38
+
39
+        $result = $qb->executeQuery();
40
+        while ($row = $result->fetchAssociative()) {
41
+            $this->discoveryService->discover($row['remote'], 'FEDERATED_SHARING', true);
42
+            try {
43
+                $this->ocmDiscoveryService->discover($row['remote'], true);
44
+            } catch (OCMProviderException $e) {
45
+                $this->logger->info('exception while running files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob', ['exception' => $e]);
46
+            }
47
+        }
48
+        $result->closeCursor();
49
+    }
50 50
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Command/CleanupRemoteStorages.php 1 patch
Indentation   +145 added lines, -145 removed lines patch added patch discarded remove patch
@@ -21,149 +21,149 @@
 block discarded – undo
21 21
  */
22 22
 class CleanupRemoteStorages extends Command {
23 23
 
24
-	public function __construct(
25
-		protected IDBConnection $connection,
26
-		private ICloudIdManager $cloudIdManager,
27
-	) {
28
-		parent::__construct();
29
-	}
30
-
31
-	protected function configure() {
32
-		$this
33
-			->setName('sharing:cleanup-remote-storages')
34
-			->setDescription('Cleanup shared storage entries that have no matching entry in the shares_external table')
35
-			->addOption(
36
-				'dry-run',
37
-				null,
38
-				InputOption::VALUE_NONE,
39
-				'only show which storages would be deleted'
40
-			);
41
-	}
42
-
43
-	public function execute(InputInterface $input, OutputInterface $output): int {
44
-		$remoteStorages = $this->getRemoteStorages();
45
-
46
-		$output->writeln(count($remoteStorages) . ' remote storage(s) need(s) to be checked');
47
-
48
-		$remoteShareIds = $this->getRemoteShareIds();
49
-
50
-		$output->writeln(count($remoteShareIds) . ' remote share(s) exist');
51
-
52
-		foreach ($remoteShareIds as $id => $remoteShareId) {
53
-			if (isset($remoteStorages[$remoteShareId])) {
54
-				if ($input->getOption('dry-run') || $output->isVerbose()) {
55
-					$output->writeln("<info>$remoteShareId belongs to remote share $id</info>");
56
-				}
57
-
58
-				unset($remoteStorages[$remoteShareId]);
59
-			} else {
60
-				$output->writeln("<comment>$remoteShareId for share $id has no matching storage, yet</comment>");
61
-			}
62
-		}
63
-
64
-		if (empty($remoteStorages)) {
65
-			$output->writeln('<info>no storages deleted</info>');
66
-		} else {
67
-			$dryRun = $input->getOption('dry-run');
68
-			foreach ($remoteStorages as $id => $numericId) {
69
-				if ($dryRun) {
70
-					$output->writeln("<error>$id [$numericId] can be deleted</error>");
71
-					$this->countFiles($numericId, $output);
72
-				} else {
73
-					$this->deleteStorage($id, $numericId, $output);
74
-				}
75
-			}
76
-		}
77
-		return 0;
78
-	}
79
-
80
-	public function countFiles($numericId, OutputInterface $output) {
81
-		$queryBuilder = $this->connection->getQueryBuilder();
82
-		$queryBuilder->select($queryBuilder->func()->count('fileid'))
83
-			->from('filecache')
84
-			->where($queryBuilder->expr()->eq(
85
-				'storage',
86
-				$queryBuilder->createNamedParameter($numericId, IQueryBuilder::PARAM_STR),
87
-				IQueryBuilder::PARAM_STR)
88
-			);
89
-		$result = $queryBuilder->executeQuery();
90
-		$count = $result->fetchOne();
91
-		$result->closeCursor();
92
-		$output->writeln("$count files can be deleted for storage $numericId");
93
-	}
94
-
95
-	public function deleteStorage($id, $numericId, OutputInterface $output) {
96
-		$queryBuilder = $this->connection->getQueryBuilder();
97
-		$queryBuilder->delete('storages')
98
-			->where($queryBuilder->expr()->eq(
99
-				'id',
100
-				$queryBuilder->createNamedParameter($id, IQueryBuilder::PARAM_STR),
101
-				IQueryBuilder::PARAM_STR)
102
-			);
103
-		$output->write("deleting $id [$numericId] ... ");
104
-		$count = $queryBuilder->executeStatement();
105
-		$output->writeln("deleted $count storage");
106
-		$this->deleteFiles($numericId, $output);
107
-	}
108
-
109
-	public function deleteFiles($numericId, OutputInterface $output) {
110
-		$queryBuilder = $this->connection->getQueryBuilder();
111
-		$queryBuilder->delete('filecache')
112
-			->where($queryBuilder->expr()->eq(
113
-				'storage',
114
-				$queryBuilder->createNamedParameter($numericId, IQueryBuilder::PARAM_STR),
115
-				IQueryBuilder::PARAM_STR)
116
-			);
117
-		$output->write("deleting files for storage $numericId ... ");
118
-		$count = $queryBuilder->executeStatement();
119
-		$output->writeln("deleted $count files");
120
-	}
121
-
122
-	public function getRemoteStorages() {
123
-		$queryBuilder = $this->connection->getQueryBuilder();
124
-		$queryBuilder->select(['id', 'numeric_id'])
125
-			->from('storages')
126
-			->where($queryBuilder->expr()->like(
127
-				'id',
128
-				// match all 'shared::' + 32 characters storages
129
-				$queryBuilder->createNamedParameter($this->connection->escapeLikeParameter('shared::') . str_repeat('_', 32)),
130
-				IQueryBuilder::PARAM_STR)
131
-			)
132
-			->andWhere($queryBuilder->expr()->notLike(
133
-				'id',
134
-				// but not the ones starting with a '/', they are for normal shares
135
-				$queryBuilder->createNamedParameter($this->connection->escapeLikeParameter('shared::/') . '%'),
136
-				IQueryBuilder::PARAM_STR)
137
-			)
138
-			->orderBy('numeric_id');
139
-		$result = $queryBuilder->executeQuery();
140
-
141
-		$remoteStorages = [];
142
-
143
-		while ($row = $result->fetchAssociative()) {
144
-			$remoteStorages[$row['id']] = $row['numeric_id'];
145
-		}
146
-		$result->closeCursor();
147
-
148
-		return $remoteStorages;
149
-	}
150
-
151
-	public function getRemoteShareIds() {
152
-		$queryBuilder = $this->connection->getQueryBuilder();
153
-		$queryBuilder->select(['id', 'share_token', 'owner', 'remote'])
154
-			->from('share_external');
155
-		$result = $queryBuilder->executeQuery();
156
-
157
-		$remoteShareIds = [];
158
-
159
-		while ($row = $result->fetchAssociative()) {
160
-			$cloudId = $this->cloudIdManager->getCloudId($row['owner'], $row['remote']);
161
-			$remote = $cloudId->getRemote();
162
-
163
-			$remoteShareIds[$row['id']] = 'shared::' . md5($row['share_token'] . '@' . $remote);
164
-		}
165
-		$result->closeCursor();
166
-
167
-		return $remoteShareIds;
168
-	}
24
+    public function __construct(
25
+        protected IDBConnection $connection,
26
+        private ICloudIdManager $cloudIdManager,
27
+    ) {
28
+        parent::__construct();
29
+    }
30
+
31
+    protected function configure() {
32
+        $this
33
+            ->setName('sharing:cleanup-remote-storages')
34
+            ->setDescription('Cleanup shared storage entries that have no matching entry in the shares_external table')
35
+            ->addOption(
36
+                'dry-run',
37
+                null,
38
+                InputOption::VALUE_NONE,
39
+                'only show which storages would be deleted'
40
+            );
41
+    }
42
+
43
+    public function execute(InputInterface $input, OutputInterface $output): int {
44
+        $remoteStorages = $this->getRemoteStorages();
45
+
46
+        $output->writeln(count($remoteStorages) . ' remote storage(s) need(s) to be checked');
47
+
48
+        $remoteShareIds = $this->getRemoteShareIds();
49
+
50
+        $output->writeln(count($remoteShareIds) . ' remote share(s) exist');
51
+
52
+        foreach ($remoteShareIds as $id => $remoteShareId) {
53
+            if (isset($remoteStorages[$remoteShareId])) {
54
+                if ($input->getOption('dry-run') || $output->isVerbose()) {
55
+                    $output->writeln("<info>$remoteShareId belongs to remote share $id</info>");
56
+                }
57
+
58
+                unset($remoteStorages[$remoteShareId]);
59
+            } else {
60
+                $output->writeln("<comment>$remoteShareId for share $id has no matching storage, yet</comment>");
61
+            }
62
+        }
63
+
64
+        if (empty($remoteStorages)) {
65
+            $output->writeln('<info>no storages deleted</info>');
66
+        } else {
67
+            $dryRun = $input->getOption('dry-run');
68
+            foreach ($remoteStorages as $id => $numericId) {
69
+                if ($dryRun) {
70
+                    $output->writeln("<error>$id [$numericId] can be deleted</error>");
71
+                    $this->countFiles($numericId, $output);
72
+                } else {
73
+                    $this->deleteStorage($id, $numericId, $output);
74
+                }
75
+            }
76
+        }
77
+        return 0;
78
+    }
79
+
80
+    public function countFiles($numericId, OutputInterface $output) {
81
+        $queryBuilder = $this->connection->getQueryBuilder();
82
+        $queryBuilder->select($queryBuilder->func()->count('fileid'))
83
+            ->from('filecache')
84
+            ->where($queryBuilder->expr()->eq(
85
+                'storage',
86
+                $queryBuilder->createNamedParameter($numericId, IQueryBuilder::PARAM_STR),
87
+                IQueryBuilder::PARAM_STR)
88
+            );
89
+        $result = $queryBuilder->executeQuery();
90
+        $count = $result->fetchOne();
91
+        $result->closeCursor();
92
+        $output->writeln("$count files can be deleted for storage $numericId");
93
+    }
94
+
95
+    public function deleteStorage($id, $numericId, OutputInterface $output) {
96
+        $queryBuilder = $this->connection->getQueryBuilder();
97
+        $queryBuilder->delete('storages')
98
+            ->where($queryBuilder->expr()->eq(
99
+                'id',
100
+                $queryBuilder->createNamedParameter($id, IQueryBuilder::PARAM_STR),
101
+                IQueryBuilder::PARAM_STR)
102
+            );
103
+        $output->write("deleting $id [$numericId] ... ");
104
+        $count = $queryBuilder->executeStatement();
105
+        $output->writeln("deleted $count storage");
106
+        $this->deleteFiles($numericId, $output);
107
+    }
108
+
109
+    public function deleteFiles($numericId, OutputInterface $output) {
110
+        $queryBuilder = $this->connection->getQueryBuilder();
111
+        $queryBuilder->delete('filecache')
112
+            ->where($queryBuilder->expr()->eq(
113
+                'storage',
114
+                $queryBuilder->createNamedParameter($numericId, IQueryBuilder::PARAM_STR),
115
+                IQueryBuilder::PARAM_STR)
116
+            );
117
+        $output->write("deleting files for storage $numericId ... ");
118
+        $count = $queryBuilder->executeStatement();
119
+        $output->writeln("deleted $count files");
120
+    }
121
+
122
+    public function getRemoteStorages() {
123
+        $queryBuilder = $this->connection->getQueryBuilder();
124
+        $queryBuilder->select(['id', 'numeric_id'])
125
+            ->from('storages')
126
+            ->where($queryBuilder->expr()->like(
127
+                'id',
128
+                // match all 'shared::' + 32 characters storages
129
+                $queryBuilder->createNamedParameter($this->connection->escapeLikeParameter('shared::') . str_repeat('_', 32)),
130
+                IQueryBuilder::PARAM_STR)
131
+            )
132
+            ->andWhere($queryBuilder->expr()->notLike(
133
+                'id',
134
+                // but not the ones starting with a '/', they are for normal shares
135
+                $queryBuilder->createNamedParameter($this->connection->escapeLikeParameter('shared::/') . '%'),
136
+                IQueryBuilder::PARAM_STR)
137
+            )
138
+            ->orderBy('numeric_id');
139
+        $result = $queryBuilder->executeQuery();
140
+
141
+        $remoteStorages = [];
142
+
143
+        while ($row = $result->fetchAssociative()) {
144
+            $remoteStorages[$row['id']] = $row['numeric_id'];
145
+        }
146
+        $result->closeCursor();
147
+
148
+        return $remoteStorages;
149
+    }
150
+
151
+    public function getRemoteShareIds() {
152
+        $queryBuilder = $this->connection->getQueryBuilder();
153
+        $queryBuilder->select(['id', 'share_token', 'owner', 'remote'])
154
+            ->from('share_external');
155
+        $result = $queryBuilder->executeQuery();
156
+
157
+        $remoteShareIds = [];
158
+
159
+        while ($row = $result->fetchAssociative()) {
160
+            $cloudId = $this->cloudIdManager->getCloudId($row['owner'], $row['remote']);
161
+            $remote = $cloudId->getRemote();
162
+
163
+            $remoteShareIds[$row['id']] = 'shared::' . md5($row['share_token'] . '@' . $remote);
164
+        }
165
+        $result->closeCursor();
166
+
167
+        return $remoteShareIds;
168
+    }
169 169
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/SharedMount.php 2 patches
Indentation   +239 added lines, -239 removed lines patch added patch discarded remove patch
@@ -28,243 +28,243 @@
 block discarded – undo
28 28
  * Shared mount points can be moved by the user
29 29
  */
30 30
 class SharedMount extends MountPoint implements MoveableMount, ISharedMountPoint {
31
-	/**
32
-	 * @var SharedStorage $storage
33
-	 */
34
-	protected $storage = null;
35
-
36
-	/** @var IShare */
37
-	private $superShare;
38
-
39
-	/** @var IShare[] */
40
-	private $groupedShares;
41
-
42
-	public function __construct(
43
-		$storage,
44
-		array $mountpoints,
45
-		$arguments,
46
-		IStorageFactory $loader,
47
-		private View $recipientView,
48
-		CappedMemoryCache $folderExistCache,
49
-		private IEventDispatcher $eventDispatcher,
50
-		private IUser $user,
51
-		bool $alreadyVerified,
52
-	) {
53
-		$this->superShare = $arguments['superShare'];
54
-		$this->groupedShares = $arguments['groupedShares'];
55
-
56
-		$absMountPoint = '/' . $user->getUID() . '/files/' . trim($this->superShare->getTarget(), '/') . '/';
57
-
58
-		// after the mountpoint is verified for the first time, only new mountpoints (e.g. groupfolders can overwrite the target)
59
-		if (!$alreadyVerified || isset($mountpoints[$absMountPoint])) {
60
-			$newMountPoint = $this->verifyMountPoint($this->superShare, $mountpoints, $folderExistCache);
61
-			$absMountPoint = '/' . $user->getUID() . '/files/' . trim($newMountPoint, '/') . '/';
62
-		}
63
-
64
-		parent::__construct($storage, $absMountPoint, $arguments, $loader, null, null, MountProvider::class);
65
-	}
66
-
67
-	/**
68
-	 * check if the parent folder exists otherwise move the mount point up
69
-	 *
70
-	 * @param IShare $share
71
-	 * @param SharedMount[] $mountpoints
72
-	 * @param CappedMemoryCache<bool> $folderExistCache
73
-	 * @return string
74
-	 */
75
-	private function verifyMountPoint(
76
-		IShare $share,
77
-		array $mountpoints,
78
-		CappedMemoryCache $folderExistCache,
79
-	) {
80
-		$mountPoint = basename($share->getTarget());
81
-		$parent = dirname($share->getTarget());
82
-
83
-		$event = new VerifyMountPointEvent($share, $this->recipientView, $parent);
84
-		$this->eventDispatcher->dispatchTyped($event);
85
-		$parent = $event->getParent();
86
-
87
-		$cached = $folderExistCache->get($parent);
88
-		if ($cached) {
89
-			$parentExists = $cached;
90
-		} else {
91
-			$parentExists = $this->recipientView->is_dir($parent);
92
-			$folderExistCache->set($parent, $parentExists);
93
-		}
94
-		if (!$parentExists) {
95
-			$parent = Helper::getShareFolder($this->recipientView, $this->user->getUID());
96
-		}
97
-
98
-		$newMountPoint = $this->generateUniqueTarget(
99
-			Filesystem::normalizePath($parent . '/' . $mountPoint),
100
-			$this->recipientView,
101
-			$mountpoints
102
-		);
103
-
104
-		if ($newMountPoint !== $share->getTarget()) {
105
-			$this->updateFileTarget($newMountPoint, $share);
106
-		}
107
-
108
-		return $newMountPoint;
109
-	}
110
-
111
-	/**
112
-	 * update fileTarget in the database if the mount point changed
113
-	 *
114
-	 * @param string $newPath
115
-	 * @param IShare $share
116
-	 * @return bool
117
-	 */
118
-	private function updateFileTarget($newPath, &$share) {
119
-		$share->setTarget($newPath);
120
-
121
-		foreach ($this->groupedShares as $tmpShare) {
122
-			$tmpShare->setTarget($newPath);
123
-			Server::get(\OCP\Share\IManager::class)->moveShare($tmpShare, $this->user->getUID());
124
-		}
125
-
126
-		$this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent($this->user));
127
-	}
128
-
129
-
130
-	/**
131
-	 * @param string $path
132
-	 * @param View $view
133
-	 * @param SharedMount[] $mountpoints
134
-	 * @return mixed
135
-	 */
136
-	private function generateUniqueTarget($path, $view, array $mountpoints) {
137
-		$pathinfo = pathinfo($path);
138
-		$ext = isset($pathinfo['extension']) ? '.' . $pathinfo['extension'] : '';
139
-		$name = $pathinfo['filename'];
140
-		$dir = $pathinfo['dirname'];
141
-
142
-		$i = 2;
143
-		$absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
144
-		while ($view->file_exists($path) || isset($mountpoints[$absolutePath])) {
145
-			$path = Filesystem::normalizePath($dir . '/' . $name . ' (' . $i . ')' . $ext);
146
-			$absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
147
-			$i++;
148
-		}
149
-
150
-		return $path;
151
-	}
152
-
153
-	/**
154
-	 * Format a path to be relative to the /user/files/ directory
155
-	 *
156
-	 * @param string $path the absolute path
157
-	 * @return string e.g. turns '/admin/files/test.txt' into '/test.txt'
158
-	 * @throws BrokenPath
159
-	 */
160
-	protected function stripUserFilesPath($path) {
161
-		$trimmed = ltrim($path, '/');
162
-		$split = explode('/', $trimmed);
163
-
164
-		// it is not a file relative to data/user/files
165
-		if (count($split) < 3 || $split[1] !== 'files') {
166
-			Server::get(LoggerInterface::class)->error('Can not strip userid and "files/" from path: ' . $path, ['app' => 'files_sharing']);
167
-			throw new BrokenPath('Path does not start with /user/files', 10);
168
-		}
169
-
170
-		// skip 'user' and 'files'
171
-		$sliced = array_slice($split, 2);
172
-		$relPath = implode('/', $sliced);
173
-
174
-		return '/' . $relPath;
175
-	}
176
-
177
-	/**
178
-	 * Move the mount point to $target
179
-	 *
180
-	 * @param string $target the target mount point
181
-	 * @return bool
182
-	 */
183
-	public function moveMount($target) {
184
-		$relTargetPath = $this->stripUserFilesPath($target);
185
-		$share = $this->storage->getShare();
186
-
187
-		$result = true;
188
-
189
-		try {
190
-			$this->updateFileTarget($relTargetPath, $share);
191
-			$this->setMountPoint($target);
192
-			$this->storage->setMountPoint($relTargetPath);
193
-		} catch (\Exception $e) {
194
-			Server::get(LoggerInterface::class)->error(
195
-				'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"',
196
-				[
197
-					'app' => 'files_sharing',
198
-					'exception' => $e,
199
-				]
200
-			);
201
-		}
202
-
203
-		return $result;
204
-	}
205
-
206
-	/**
207
-	 * Remove the mount points
208
-	 *
209
-	 * @return bool
210
-	 */
211
-	public function removeMount() {
212
-		$mountManager = Filesystem::getMountManager();
213
-		/** @var SharedStorage $storage */
214
-		$storage = $this->getStorage();
215
-		$result = $storage->unshareStorage();
216
-		$mountManager->removeMount($this->mountPoint);
217
-
218
-		return $result;
219
-	}
220
-
221
-	/**
222
-	 * @return IShare
223
-	 */
224
-	public function getShare() {
225
-		return $this->superShare;
226
-	}
227
-
228
-	/**
229
-	 * @return IShare[]
230
-	 */
231
-	public function getGroupedShares(): array {
232
-		return $this->groupedShares;
233
-	}
234
-
235
-	/**
236
-	 * Get the file id of the root of the storage
237
-	 *
238
-	 * @return int
239
-	 */
240
-	public function getStorageRootId() {
241
-		return $this->getShare()->getNodeId();
242
-	}
243
-
244
-	/**
245
-	 * @return int
246
-	 */
247
-	public function getNumericStorageId() {
248
-		if (!is_null($this->getShare()->getNodeCacheEntry())) {
249
-			return $this->getShare()->getNodeCacheEntry()->getStorageId();
250
-		} else {
251
-			$builder = Server::get(IDBConnection::class)->getQueryBuilder();
252
-
253
-			$query = $builder->select('storage')
254
-				->from('filecache')
255
-				->where($builder->expr()->eq('fileid', $builder->createNamedParameter($this->getStorageRootId())));
256
-
257
-			$result = $query->executeQuery();
258
-			$row = $result->fetchAssociative();
259
-			$result->closeCursor();
260
-			if ($row) {
261
-				return (int)$row['storage'];
262
-			}
263
-			return -1;
264
-		}
265
-	}
266
-
267
-	public function getMountType() {
268
-		return 'shared';
269
-	}
31
+    /**
32
+     * @var SharedStorage $storage
33
+     */
34
+    protected $storage = null;
35
+
36
+    /** @var IShare */
37
+    private $superShare;
38
+
39
+    /** @var IShare[] */
40
+    private $groupedShares;
41
+
42
+    public function __construct(
43
+        $storage,
44
+        array $mountpoints,
45
+        $arguments,
46
+        IStorageFactory $loader,
47
+        private View $recipientView,
48
+        CappedMemoryCache $folderExistCache,
49
+        private IEventDispatcher $eventDispatcher,
50
+        private IUser $user,
51
+        bool $alreadyVerified,
52
+    ) {
53
+        $this->superShare = $arguments['superShare'];
54
+        $this->groupedShares = $arguments['groupedShares'];
55
+
56
+        $absMountPoint = '/' . $user->getUID() . '/files/' . trim($this->superShare->getTarget(), '/') . '/';
57
+
58
+        // after the mountpoint is verified for the first time, only new mountpoints (e.g. groupfolders can overwrite the target)
59
+        if (!$alreadyVerified || isset($mountpoints[$absMountPoint])) {
60
+            $newMountPoint = $this->verifyMountPoint($this->superShare, $mountpoints, $folderExistCache);
61
+            $absMountPoint = '/' . $user->getUID() . '/files/' . trim($newMountPoint, '/') . '/';
62
+        }
63
+
64
+        parent::__construct($storage, $absMountPoint, $arguments, $loader, null, null, MountProvider::class);
65
+    }
66
+
67
+    /**
68
+     * check if the parent folder exists otherwise move the mount point up
69
+     *
70
+     * @param IShare $share
71
+     * @param SharedMount[] $mountpoints
72
+     * @param CappedMemoryCache<bool> $folderExistCache
73
+     * @return string
74
+     */
75
+    private function verifyMountPoint(
76
+        IShare $share,
77
+        array $mountpoints,
78
+        CappedMemoryCache $folderExistCache,
79
+    ) {
80
+        $mountPoint = basename($share->getTarget());
81
+        $parent = dirname($share->getTarget());
82
+
83
+        $event = new VerifyMountPointEvent($share, $this->recipientView, $parent);
84
+        $this->eventDispatcher->dispatchTyped($event);
85
+        $parent = $event->getParent();
86
+
87
+        $cached = $folderExistCache->get($parent);
88
+        if ($cached) {
89
+            $parentExists = $cached;
90
+        } else {
91
+            $parentExists = $this->recipientView->is_dir($parent);
92
+            $folderExistCache->set($parent, $parentExists);
93
+        }
94
+        if (!$parentExists) {
95
+            $parent = Helper::getShareFolder($this->recipientView, $this->user->getUID());
96
+        }
97
+
98
+        $newMountPoint = $this->generateUniqueTarget(
99
+            Filesystem::normalizePath($parent . '/' . $mountPoint),
100
+            $this->recipientView,
101
+            $mountpoints
102
+        );
103
+
104
+        if ($newMountPoint !== $share->getTarget()) {
105
+            $this->updateFileTarget($newMountPoint, $share);
106
+        }
107
+
108
+        return $newMountPoint;
109
+    }
110
+
111
+    /**
112
+     * update fileTarget in the database if the mount point changed
113
+     *
114
+     * @param string $newPath
115
+     * @param IShare $share
116
+     * @return bool
117
+     */
118
+    private function updateFileTarget($newPath, &$share) {
119
+        $share->setTarget($newPath);
120
+
121
+        foreach ($this->groupedShares as $tmpShare) {
122
+            $tmpShare->setTarget($newPath);
123
+            Server::get(\OCP\Share\IManager::class)->moveShare($tmpShare, $this->user->getUID());
124
+        }
125
+
126
+        $this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent($this->user));
127
+    }
128
+
129
+
130
+    /**
131
+     * @param string $path
132
+     * @param View $view
133
+     * @param SharedMount[] $mountpoints
134
+     * @return mixed
135
+     */
136
+    private function generateUniqueTarget($path, $view, array $mountpoints) {
137
+        $pathinfo = pathinfo($path);
138
+        $ext = isset($pathinfo['extension']) ? '.' . $pathinfo['extension'] : '';
139
+        $name = $pathinfo['filename'];
140
+        $dir = $pathinfo['dirname'];
141
+
142
+        $i = 2;
143
+        $absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
144
+        while ($view->file_exists($path) || isset($mountpoints[$absolutePath])) {
145
+            $path = Filesystem::normalizePath($dir . '/' . $name . ' (' . $i . ')' . $ext);
146
+            $absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
147
+            $i++;
148
+        }
149
+
150
+        return $path;
151
+    }
152
+
153
+    /**
154
+     * Format a path to be relative to the /user/files/ directory
155
+     *
156
+     * @param string $path the absolute path
157
+     * @return string e.g. turns '/admin/files/test.txt' into '/test.txt'
158
+     * @throws BrokenPath
159
+     */
160
+    protected function stripUserFilesPath($path) {
161
+        $trimmed = ltrim($path, '/');
162
+        $split = explode('/', $trimmed);
163
+
164
+        // it is not a file relative to data/user/files
165
+        if (count($split) < 3 || $split[1] !== 'files') {
166
+            Server::get(LoggerInterface::class)->error('Can not strip userid and "files/" from path: ' . $path, ['app' => 'files_sharing']);
167
+            throw new BrokenPath('Path does not start with /user/files', 10);
168
+        }
169
+
170
+        // skip 'user' and 'files'
171
+        $sliced = array_slice($split, 2);
172
+        $relPath = implode('/', $sliced);
173
+
174
+        return '/' . $relPath;
175
+    }
176
+
177
+    /**
178
+     * Move the mount point to $target
179
+     *
180
+     * @param string $target the target mount point
181
+     * @return bool
182
+     */
183
+    public function moveMount($target) {
184
+        $relTargetPath = $this->stripUserFilesPath($target);
185
+        $share = $this->storage->getShare();
186
+
187
+        $result = true;
188
+
189
+        try {
190
+            $this->updateFileTarget($relTargetPath, $share);
191
+            $this->setMountPoint($target);
192
+            $this->storage->setMountPoint($relTargetPath);
193
+        } catch (\Exception $e) {
194
+            Server::get(LoggerInterface::class)->error(
195
+                'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"',
196
+                [
197
+                    'app' => 'files_sharing',
198
+                    'exception' => $e,
199
+                ]
200
+            );
201
+        }
202
+
203
+        return $result;
204
+    }
205
+
206
+    /**
207
+     * Remove the mount points
208
+     *
209
+     * @return bool
210
+     */
211
+    public function removeMount() {
212
+        $mountManager = Filesystem::getMountManager();
213
+        /** @var SharedStorage $storage */
214
+        $storage = $this->getStorage();
215
+        $result = $storage->unshareStorage();
216
+        $mountManager->removeMount($this->mountPoint);
217
+
218
+        return $result;
219
+    }
220
+
221
+    /**
222
+     * @return IShare
223
+     */
224
+    public function getShare() {
225
+        return $this->superShare;
226
+    }
227
+
228
+    /**
229
+     * @return IShare[]
230
+     */
231
+    public function getGroupedShares(): array {
232
+        return $this->groupedShares;
233
+    }
234
+
235
+    /**
236
+     * Get the file id of the root of the storage
237
+     *
238
+     * @return int
239
+     */
240
+    public function getStorageRootId() {
241
+        return $this->getShare()->getNodeId();
242
+    }
243
+
244
+    /**
245
+     * @return int
246
+     */
247
+    public function getNumericStorageId() {
248
+        if (!is_null($this->getShare()->getNodeCacheEntry())) {
249
+            return $this->getShare()->getNodeCacheEntry()->getStorageId();
250
+        } else {
251
+            $builder = Server::get(IDBConnection::class)->getQueryBuilder();
252
+
253
+            $query = $builder->select('storage')
254
+                ->from('filecache')
255
+                ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($this->getStorageRootId())));
256
+
257
+            $result = $query->executeQuery();
258
+            $row = $result->fetchAssociative();
259
+            $result->closeCursor();
260
+            if ($row) {
261
+                return (int)$row['storage'];
262
+            }
263
+            return -1;
264
+        }
265
+    }
266
+
267
+    public function getMountType() {
268
+        return 'shared';
269
+    }
270 270
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -53,12 +53,12 @@  discard block
 block discarded – undo
53 53
 		$this->superShare = $arguments['superShare'];
54 54
 		$this->groupedShares = $arguments['groupedShares'];
55 55
 
56
-		$absMountPoint = '/' . $user->getUID() . '/files/' . trim($this->superShare->getTarget(), '/') . '/';
56
+		$absMountPoint = '/'.$user->getUID().'/files/'.trim($this->superShare->getTarget(), '/').'/';
57 57
 
58 58
 		// after the mountpoint is verified for the first time, only new mountpoints (e.g. groupfolders can overwrite the target)
59 59
 		if (!$alreadyVerified || isset($mountpoints[$absMountPoint])) {
60 60
 			$newMountPoint = $this->verifyMountPoint($this->superShare, $mountpoints, $folderExistCache);
61
-			$absMountPoint = '/' . $user->getUID() . '/files/' . trim($newMountPoint, '/') . '/';
61
+			$absMountPoint = '/'.$user->getUID().'/files/'.trim($newMountPoint, '/').'/';
62 62
 		}
63 63
 
64 64
 		parent::__construct($storage, $absMountPoint, $arguments, $loader, null, null, MountProvider::class);
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 		}
97 97
 
98 98
 		$newMountPoint = $this->generateUniqueTarget(
99
-			Filesystem::normalizePath($parent . '/' . $mountPoint),
99
+			Filesystem::normalizePath($parent.'/'.$mountPoint),
100 100
 			$this->recipientView,
101 101
 			$mountpoints
102 102
 		);
@@ -135,15 +135,15 @@  discard block
 block discarded – undo
135 135
 	 */
136 136
 	private function generateUniqueTarget($path, $view, array $mountpoints) {
137 137
 		$pathinfo = pathinfo($path);
138
-		$ext = isset($pathinfo['extension']) ? '.' . $pathinfo['extension'] : '';
138
+		$ext = isset($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
139 139
 		$name = $pathinfo['filename'];
140 140
 		$dir = $pathinfo['dirname'];
141 141
 
142 142
 		$i = 2;
143
-		$absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
143
+		$absolutePath = $this->recipientView->getAbsolutePath($path).'/';
144 144
 		while ($view->file_exists($path) || isset($mountpoints[$absolutePath])) {
145
-			$path = Filesystem::normalizePath($dir . '/' . $name . ' (' . $i . ')' . $ext);
146
-			$absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
145
+			$path = Filesystem::normalizePath($dir.'/'.$name.' ('.$i.')'.$ext);
146
+			$absolutePath = $this->recipientView->getAbsolutePath($path).'/';
147 147
 			$i++;
148 148
 		}
149 149
 
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
 
164 164
 		// it is not a file relative to data/user/files
165 165
 		if (count($split) < 3 || $split[1] !== 'files') {
166
-			Server::get(LoggerInterface::class)->error('Can not strip userid and "files/" from path: ' . $path, ['app' => 'files_sharing']);
166
+			Server::get(LoggerInterface::class)->error('Can not strip userid and "files/" from path: '.$path, ['app' => 'files_sharing']);
167 167
 			throw new BrokenPath('Path does not start with /user/files', 10);
168 168
 		}
169 169
 
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 		$sliced = array_slice($split, 2);
172 172
 		$relPath = implode('/', $sliced);
173 173
 
174
-		return '/' . $relPath;
174
+		return '/'.$relPath;
175 175
 	}
176 176
 
177 177
 	/**
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
 			$this->storage->setMountPoint($relTargetPath);
193 193
 		} catch (\Exception $e) {
194 194
 			Server::get(LoggerInterface::class)->error(
195
-				'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"',
195
+				'Could not rename mount point for shared folder "'.$this->getMountPoint().'" to "'.$target.'"',
196 196
 				[
197 197
 					'app' => 'files_sharing',
198 198
 					'exception' => $e,
@@ -258,7 +258,7 @@  discard block
 block discarded – undo
258 258
 			$row = $result->fetchAssociative();
259 259
 			$result->closeCursor();
260 260
 			if ($row) {
261
-				return (int)$row['storage'];
261
+				return (int) $row['storage'];
262 262
 			}
263 263
 			return -1;
264 264
 		}
Please login to merge, or discard this patch.
apps/files_sharing/lib/DeleteOrphanedSharesJob.php 2 patches
Indentation   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -21,112 +21,112 @@
 block discarded – undo
21 21
  */
22 22
 class DeleteOrphanedSharesJob extends TimedJob {
23 23
 
24
-	use TTransactional;
24
+    use TTransactional;
25 25
 
26
-	private const CHUNK_SIZE = 1000;
26
+    private const CHUNK_SIZE = 1000;
27 27
 
28
-	private const INTERVAL = 24 * 60 * 60;
28
+    private const INTERVAL = 24 * 60 * 60;
29 29
 
30
-	/**
31
-	 * sets the correct interval for this timed job
32
-	 */
33
-	public function __construct(
34
-		ITimeFactory $time,
35
-		private IDBConnection $db,
36
-		private LoggerInterface $logger,
37
-	) {
38
-		parent::__construct($time);
30
+    /**
31
+     * sets the correct interval for this timed job
32
+     */
33
+    public function __construct(
34
+        ITimeFactory $time,
35
+        private IDBConnection $db,
36
+        private LoggerInterface $logger,
37
+    ) {
38
+        parent::__construct($time);
39 39
 
40
-		$this->setInterval(self::INTERVAL); // 1 day
41
-		$this->setTimeSensitivity(self::TIME_INSENSITIVE);
42
-	}
40
+        $this->setInterval(self::INTERVAL); // 1 day
41
+        $this->setTimeSensitivity(self::TIME_INSENSITIVE);
42
+    }
43 43
 
44
-	/**
45
-	 * Makes the background job do its work
46
-	 *
47
-	 * @param array $argument unused argument
48
-	 */
49
-	public function run($argument) {
50
-		if ($this->db->getShardDefinition('filecache')) {
51
-			$this->shardingCleanup();
52
-			return;
53
-		}
44
+    /**
45
+     * Makes the background job do its work
46
+     *
47
+     * @param array $argument unused argument
48
+     */
49
+    public function run($argument) {
50
+        if ($this->db->getShardDefinition('filecache')) {
51
+            $this->shardingCleanup();
52
+            return;
53
+        }
54 54
 
55
-		$qbSelect = $this->db->getQueryBuilder();
56
-		$qbSelect->select('id')
57
-			->from('share', 's')
58
-			->leftJoin('s', 'filecache', 'fc', $qbSelect->expr()->eq('s.file_source', 'fc.fileid'))
59
-			->where($qbSelect->expr()->isNull('fc.fileid'))
60
-			->setMaxResults(self::CHUNK_SIZE);
61
-		$deleteQb = $this->db->getQueryBuilder();
62
-		$deleteQb->delete('share')
63
-			->where(
64
-				$deleteQb->expr()->in('id', $deleteQb->createParameter('ids'), IQueryBuilder::PARAM_INT_ARRAY)
65
-			);
55
+        $qbSelect = $this->db->getQueryBuilder();
56
+        $qbSelect->select('id')
57
+            ->from('share', 's')
58
+            ->leftJoin('s', 'filecache', 'fc', $qbSelect->expr()->eq('s.file_source', 'fc.fileid'))
59
+            ->where($qbSelect->expr()->isNull('fc.fileid'))
60
+            ->setMaxResults(self::CHUNK_SIZE);
61
+        $deleteQb = $this->db->getQueryBuilder();
62
+        $deleteQb->delete('share')
63
+            ->where(
64
+                $deleteQb->expr()->in('id', $deleteQb->createParameter('ids'), IQueryBuilder::PARAM_INT_ARRAY)
65
+            );
66 66
 
67
-		/**
68
-		 * Read a chunk of orphan rows and delete them. Continue as long as the
69
-		 * chunk is filled and time before the next cron run does not run out.
70
-		 *
71
-		 * Note: With isolation level READ COMMITTED, the database will allow
72
-		 * other transactions to delete rows between our SELECT and DELETE. In
73
-		 * that (unlikely) case, our DELETE will have fewer affected rows than
74
-		 * IDs passed for the WHERE IN. If this happens while processing a full
75
-		 * chunk, the logic below will stop prematurely.
76
-		 * Note: The queries below are optimized for low database locking. They
77
-		 * could be combined into one single DELETE with join or sub query, but
78
-		 * that has shown to (dead)lock often.
79
-		 */
80
-		$cutOff = $this->time->getTime() + self::INTERVAL;
81
-		do {
82
-			$deleted = $this->atomic(function () use ($qbSelect, $deleteQb) {
83
-				$result = $qbSelect->executeQuery();
84
-				$ids = array_map('intval', $result->fetchFirstColumn());
85
-				$result->closeCursor();
86
-				$deleteQb->setParameter('ids', $ids, IQueryBuilder::PARAM_INT_ARRAY);
87
-				$deleted = $deleteQb->executeStatement();
88
-				$this->logger->debug('{deleted} orphaned share(s) deleted', [
89
-					'app' => 'DeleteOrphanedSharesJob',
90
-					'deleted' => $deleted,
91
-				]);
92
-				return $deleted;
93
-			}, $this->db);
94
-		} while ($deleted >= self::CHUNK_SIZE && $this->time->getTime() <= $cutOff);
95
-	}
67
+        /**
68
+         * Read a chunk of orphan rows and delete them. Continue as long as the
69
+         * chunk is filled and time before the next cron run does not run out.
70
+         *
71
+         * Note: With isolation level READ COMMITTED, the database will allow
72
+         * other transactions to delete rows between our SELECT and DELETE. In
73
+         * that (unlikely) case, our DELETE will have fewer affected rows than
74
+         * IDs passed for the WHERE IN. If this happens while processing a full
75
+         * chunk, the logic below will stop prematurely.
76
+         * Note: The queries below are optimized for low database locking. They
77
+         * could be combined into one single DELETE with join or sub query, but
78
+         * that has shown to (dead)lock often.
79
+         */
80
+        $cutOff = $this->time->getTime() + self::INTERVAL;
81
+        do {
82
+            $deleted = $this->atomic(function () use ($qbSelect, $deleteQb) {
83
+                $result = $qbSelect->executeQuery();
84
+                $ids = array_map('intval', $result->fetchFirstColumn());
85
+                $result->closeCursor();
86
+                $deleteQb->setParameter('ids', $ids, IQueryBuilder::PARAM_INT_ARRAY);
87
+                $deleted = $deleteQb->executeStatement();
88
+                $this->logger->debug('{deleted} orphaned share(s) deleted', [
89
+                    'app' => 'DeleteOrphanedSharesJob',
90
+                    'deleted' => $deleted,
91
+                ]);
92
+                return $deleted;
93
+            }, $this->db);
94
+        } while ($deleted >= self::CHUNK_SIZE && $this->time->getTime() <= $cutOff);
95
+    }
96 96
 
97
-	private function shardingCleanup(): void {
98
-		$qb = $this->db->getQueryBuilder();
99
-		$qb->selectDistinct('file_source')
100
-			->from('share', 's');
101
-		$sourceFiles = $qb->executeQuery()->fetchFirstColumn();
97
+    private function shardingCleanup(): void {
98
+        $qb = $this->db->getQueryBuilder();
99
+        $qb->selectDistinct('file_source')
100
+            ->from('share', 's');
101
+        $sourceFiles = $qb->executeQuery()->fetchFirstColumn();
102 102
 
103
-		$deleteQb = $this->db->getQueryBuilder();
104
-		$deleteQb->delete('share')
105
-			->where(
106
-				$deleteQb->expr()->in('file_source', $deleteQb->createParameter('ids'), IQueryBuilder::PARAM_INT_ARRAY)
107
-			);
103
+        $deleteQb = $this->db->getQueryBuilder();
104
+        $deleteQb->delete('share')
105
+            ->where(
106
+                $deleteQb->expr()->in('file_source', $deleteQb->createParameter('ids'), IQueryBuilder::PARAM_INT_ARRAY)
107
+            );
108 108
 
109
-		$chunks = array_chunk($sourceFiles, self::CHUNK_SIZE);
110
-		foreach ($chunks as $chunk) {
111
-			$deletedFiles = $this->findMissingSources($chunk);
112
-			$this->atomic(function () use ($deletedFiles, $deleteQb) {
113
-				$deleteQb->setParameter('ids', $deletedFiles, IQueryBuilder::PARAM_INT_ARRAY);
114
-				$deleted = $deleteQb->executeStatement();
115
-				$this->logger->debug('{deleted} orphaned share(s) deleted', [
116
-					'app' => 'DeleteOrphanedSharesJob',
117
-					'deleted' => $deleted,
118
-				]);
119
-				return $deleted;
120
-			}, $this->db);
121
-		}
122
-	}
109
+        $chunks = array_chunk($sourceFiles, self::CHUNK_SIZE);
110
+        foreach ($chunks as $chunk) {
111
+            $deletedFiles = $this->findMissingSources($chunk);
112
+            $this->atomic(function () use ($deletedFiles, $deleteQb) {
113
+                $deleteQb->setParameter('ids', $deletedFiles, IQueryBuilder::PARAM_INT_ARRAY);
114
+                $deleted = $deleteQb->executeStatement();
115
+                $this->logger->debug('{deleted} orphaned share(s) deleted', [
116
+                    'app' => 'DeleteOrphanedSharesJob',
117
+                    'deleted' => $deleted,
118
+                ]);
119
+                return $deleted;
120
+            }, $this->db);
121
+        }
122
+    }
123 123
 
124
-	private function findMissingSources(array $ids): array {
125
-		$qb = $this->db->getQueryBuilder();
126
-		$qb->select('fileid')
127
-			->from('filecache')
128
-			->where($qb->expr()->in('fileid', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
129
-		$found = $qb->executeQuery()->fetchFirstColumn();
130
-		return array_diff($ids, $found);
131
-	}
124
+    private function findMissingSources(array $ids): array {
125
+        $qb = $this->db->getQueryBuilder();
126
+        $qb->select('fileid')
127
+            ->from('filecache')
128
+            ->where($qb->expr()->in('fileid', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
129
+        $found = $qb->executeQuery()->fetchFirstColumn();
130
+        return array_diff($ids, $found);
131
+    }
132 132
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
 		 */
80 80
 		$cutOff = $this->time->getTime() + self::INTERVAL;
81 81
 		do {
82
-			$deleted = $this->atomic(function () use ($qbSelect, $deleteQb) {
82
+			$deleted = $this->atomic(function() use ($qbSelect, $deleteQb) {
83 83
 				$result = $qbSelect->executeQuery();
84 84
 				$ids = array_map('intval', $result->fetchFirstColumn());
85 85
 				$result->closeCursor();
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
 		$chunks = array_chunk($sourceFiles, self::CHUNK_SIZE);
110 110
 		foreach ($chunks as $chunk) {
111 111
 			$deletedFiles = $this->findMissingSources($chunk);
112
-			$this->atomic(function () use ($deletedFiles, $deleteQb) {
112
+			$this->atomic(function() use ($deletedFiles, $deleteQb) {
113 113
 				$deleteQb->setParameter('ids', $deletedFiles, IQueryBuilder::PARAM_INT_ARRAY);
114 114
 				$deleted = $deleteQb->executeStatement();
115 115
 				$this->logger->debug('{deleted} orphaned share(s) deleted', [
Please login to merge, or discard this patch.
apps/files_sharing/lib/External/MountProvider.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -17,52 +17,52 @@
 block discarded – undo
17 17
 use OCP\Server;
18 18
 
19 19
 class MountProvider implements IMountProvider {
20
-	public const STORAGE = '\OCA\Files_Sharing\External\Storage';
20
+    public const STORAGE = '\OCA\Files_Sharing\External\Storage';
21 21
 
22
-	/**
23
-	 * @var callable
24
-	 */
25
-	private $managerProvider;
22
+    /**
23
+     * @var callable
24
+     */
25
+    private $managerProvider;
26 26
 
27
-	/**
28
-	 * @param IDBConnection $connection
29
-	 * @param callable $managerProvider due to setup order we need a callable that return the manager instead of the manager itself
30
-	 * @param ICloudIdManager $cloudIdManager
31
-	 */
32
-	public function __construct(
33
-		private IDBConnection $connection,
34
-		callable $managerProvider,
35
-		private ICloudIdManager $cloudIdManager,
36
-	) {
37
-		$this->managerProvider = $managerProvider;
38
-	}
27
+    /**
28
+     * @param IDBConnection $connection
29
+     * @param callable $managerProvider due to setup order we need a callable that return the manager instead of the manager itself
30
+     * @param ICloudIdManager $cloudIdManager
31
+     */
32
+    public function __construct(
33
+        private IDBConnection $connection,
34
+        callable $managerProvider,
35
+        private ICloudIdManager $cloudIdManager,
36
+    ) {
37
+        $this->managerProvider = $managerProvider;
38
+    }
39 39
 
40
-	public function getMount(IUser $user, $data, IStorageFactory $storageFactory) {
41
-		$managerProvider = $this->managerProvider;
42
-		$manager = $managerProvider();
43
-		$data['manager'] = $manager;
44
-		$mountPoint = '/' . $user->getUID() . '/files/' . ltrim($data['mountpoint'], '/');
45
-		$data['mountpoint'] = $mountPoint;
46
-		$data['cloudId'] = $this->cloudIdManager->getCloudId($data['owner'], $data['remote']);
47
-		$data['certificateManager'] = \OC::$server->getCertificateManager();
48
-		$data['HttpClientService'] = Server::get(IClientService::class);
49
-		return new Mount(self::STORAGE, $mountPoint, $data, $manager, $storageFactory);
50
-	}
40
+    public function getMount(IUser $user, $data, IStorageFactory $storageFactory) {
41
+        $managerProvider = $this->managerProvider;
42
+        $manager = $managerProvider();
43
+        $data['manager'] = $manager;
44
+        $mountPoint = '/' . $user->getUID() . '/files/' . ltrim($data['mountpoint'], '/');
45
+        $data['mountpoint'] = $mountPoint;
46
+        $data['cloudId'] = $this->cloudIdManager->getCloudId($data['owner'], $data['remote']);
47
+        $data['certificateManager'] = \OC::$server->getCertificateManager();
48
+        $data['HttpClientService'] = Server::get(IClientService::class);
49
+        return new Mount(self::STORAGE, $mountPoint, $data, $manager, $storageFactory);
50
+    }
51 51
 
52
-	public function getMountsForUser(IUser $user, IStorageFactory $loader) {
53
-		$qb = $this->connection->getQueryBuilder();
54
-		$qb->select('remote', 'share_token', 'password', 'mountpoint', 'owner')
55
-			->from('share_external')
56
-			->where($qb->expr()->eq('user', $qb->createNamedParameter($user->getUID())))
57
-			->andWhere($qb->expr()->eq('accepted', $qb->createNamedParameter(1, IQueryBuilder::PARAM_INT)));
58
-		$result = $qb->executeQuery();
59
-		$mounts = [];
60
-		while ($row = $result->fetchAssociative()) {
61
-			$row['manager'] = $this;
62
-			$row['token'] = $row['share_token'];
63
-			$mounts[] = $this->getMount($user, $row, $loader);
64
-		}
65
-		$result->closeCursor();
66
-		return $mounts;
67
-	}
52
+    public function getMountsForUser(IUser $user, IStorageFactory $loader) {
53
+        $qb = $this->connection->getQueryBuilder();
54
+        $qb->select('remote', 'share_token', 'password', 'mountpoint', 'owner')
55
+            ->from('share_external')
56
+            ->where($qb->expr()->eq('user', $qb->createNamedParameter($user->getUID())))
57
+            ->andWhere($qb->expr()->eq('accepted', $qb->createNamedParameter(1, IQueryBuilder::PARAM_INT)));
58
+        $result = $qb->executeQuery();
59
+        $mounts = [];
60
+        while ($row = $result->fetchAssociative()) {
61
+            $row['manager'] = $this;
62
+            $row['token'] = $row['share_token'];
63
+            $mounts[] = $this->getMount($user, $row, $loader);
64
+        }
65
+        $result->closeCursor();
66
+        return $mounts;
67
+    }
68 68
 }
Please login to merge, or discard this patch.