Completed
Push — master ( 14f798...42f450 )
by
unknown
31:50 queued 14s
created
apps/files_versions/lib/Listener/FileEventsListener.php 1 patch
Indentation   +362 added lines, -362 removed lines patch added patch discarded remove patch
@@ -42,366 +42,366 @@
 block discarded – undo
42 42
 
43 43
 /** @template-implements IEventListener<BeforeNodeCopiedEvent|BeforeNodeDeletedEvent|BeforeNodeRenamedEvent|BeforeNodeTouchedEvent|BeforeNodeWrittenEvent|NodeCopiedEvent|NodeCreatedEvent|NodeDeletedEvent|NodeRenamedEvent|NodeTouchedEvent|NodeWrittenEvent> */
44 44
 class FileEventsListener implements IEventListener {
45
-	/**
46
-	 * @var array<int, array>
47
-	 */
48
-	private array $writeHookInfo = [];
49
-	/**
50
-	 * @var array<int, Node>
51
-	 */
52
-	private array $nodesTouched = [];
53
-	/**
54
-	 * @var array<string, Node>
55
-	 */
56
-	private array $versionsDeleted = [];
57
-
58
-	public function __construct(
59
-		private IRootFolder $rootFolder,
60
-		private IVersionManager $versionManager,
61
-		private IMimeTypeLoader $mimeTypeLoader,
62
-		private IUserSession $userSession,
63
-		private LoggerInterface $logger,
64
-	) {
65
-	}
66
-
67
-	public function handle(Event $event): void {
68
-		if ($event instanceof NodeCreatedEvent) {
69
-			$this->created($event->getNode());
70
-		}
71
-
72
-		if ($event instanceof BeforeNodeTouchedEvent) {
73
-			$this->pre_touch_hook($event->getNode());
74
-		}
75
-
76
-		if ($event instanceof NodeTouchedEvent) {
77
-			$this->touch_hook($event->getNode());
78
-		}
79
-
80
-		if ($event instanceof BeforeNodeWrittenEvent) {
81
-			$this->write_hook($event->getNode());
82
-		}
83
-
84
-		if ($event instanceof NodeWrittenEvent) {
85
-			$this->post_write_hook($event->getNode());
86
-		}
87
-
88
-		if ($event instanceof BeforeNodeDeletedEvent) {
89
-			$this->pre_remove_hook($event->getNode());
90
-		}
91
-
92
-		if ($event instanceof NodeDeletedEvent) {
93
-			$this->remove_hook($event->getNode());
94
-		}
95
-
96
-		if ($event instanceof NodeRenamedEvent) {
97
-			$this->rename_hook($event->getSource(), $event->getTarget());
98
-		}
99
-
100
-		if ($event instanceof NodeCopiedEvent) {
101
-			$this->copy_hook($event->getSource(), $event->getTarget());
102
-		}
103
-
104
-		if ($event instanceof BeforeNodeRenamedEvent) {
105
-			$this->pre_renameOrCopy_hook($event->getSource(), $event->getTarget());
106
-		}
107
-
108
-		if ($event instanceof BeforeNodeCopiedEvent) {
109
-			$this->pre_renameOrCopy_hook($event->getSource(), $event->getTarget());
110
-		}
111
-	}
112
-
113
-	public function pre_touch_hook(Node $node): void {
114
-		// Do not handle folders.
115
-		if ($node instanceof Folder) {
116
-			return;
117
-		}
118
-
119
-		// $node is a non-existing on file creation.
120
-		if ($node instanceof NonExistingFile) {
121
-			return;
122
-		}
123
-
124
-		$this->nodesTouched[$node->getId()] = $node;
125
-	}
126
-
127
-	public function touch_hook(Node $node): void {
128
-		$previousNode = $this->nodesTouched[$node->getId()] ?? null;
129
-
130
-		if ($previousNode === null) {
131
-			return;
132
-		}
133
-
134
-		unset($this->nodesTouched[$node->getId()]);
135
-
136
-		try {
137
-			if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
138
-				// We update the timestamp of the version entity associated with the previousNode.
139
-				$this->versionManager->updateVersionEntity($node, $previousNode->getMTime(), ['timestamp' => $node->getMTime()]);
140
-			}
141
-		} catch (DbalException $ex) {
142
-			// Ignore UniqueConstraintViolationException, as we are probably in the middle of a rollback
143
-			// Where the previous node would temporary have the mtime of the old version, so the rollback touches it to fix it.
144
-			if (!($ex->getPrevious() instanceof UniqueConstraintViolationException)) {
145
-				throw $ex;
146
-			}
147
-		} catch (DoesNotExistException $ex) {
148
-			// Ignore DoesNotExistException, as we are probably in the middle of a rollback
149
-			// Where the previous node would temporary have a wrong mtime, so the rollback touches it to fix it.
150
-		}
151
-	}
152
-
153
-	public function created(Node $node): void {
154
-		// Do not handle folders.
155
-		if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
156
-			$this->versionManager->createVersionEntity($node);
157
-		}
158
-	}
159
-
160
-	/**
161
-	 * listen to write event.
162
-	 */
163
-	public function write_hook(Node $node): void {
164
-		// Do not handle folders.
165
-		if ($node instanceof Folder) {
166
-			return;
167
-		}
168
-
169
-		// $node is a non-existing on file creation.
170
-		if ($node instanceof NonExistingFile) {
171
-			return;
172
-		}
173
-
174
-		$path = $this->getPathForNode($node);
175
-		$result = Storage::store($path);
176
-
177
-		// Store the result of the version creation so it can be used in post_write_hook.
178
-		$this->writeHookInfo[$node->getId()] = [
179
-			'previousNode' => $node,
180
-			'versionCreated' => $result !== false
181
-		];
182
-	}
183
-
184
-	/**
185
-	 * listen to post_write event.
186
-	 */
187
-	public function post_write_hook(Node $node): void {
188
-		// Do not handle folders.
189
-		if ($node instanceof Folder) {
190
-			return;
191
-		}
192
-
193
-		$writeHookInfo = $this->writeHookInfo[$node->getId()] ?? null;
194
-
195
-		if ($writeHookInfo === null) {
196
-			return;
197
-		}
198
-
199
-		if (
200
-			$writeHookInfo['versionCreated']
201
-			&& $node->getMTime() !== $writeHookInfo['previousNode']->getMTime()
202
-		) {
203
-			// If a new version was created, insert a version in the DB for the current content.
204
-			// If both versions have the same mtime, it means the latest version file simply got overrode,
205
-			// so no need to create a new version.
206
-			$this->created($node);
207
-		} else {
208
-			try {
209
-				// If no new version was stored in the FS, no new version should be added in the DB.
210
-				// So we simply update the associated version.
211
-				if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
212
-					$this->versionManager->updateVersionEntity(
213
-						$node,
214
-						$writeHookInfo['previousNode']->getMtime(),
215
-						[
216
-							'timestamp' => $node->getMTime(),
217
-							'size' => $node->getSize(),
218
-							'mimetype' => $this->mimeTypeLoader->getId($node->getMimetype()),
219
-						],
220
-					);
221
-				}
222
-			} catch (DoesNotExistException $e) {
223
-				// This happens if the versions app was not enabled while the file was created or updated the last time.
224
-				// meaning there is no such revision and we need to create this file.
225
-				if ($writeHookInfo['versionCreated']) {
226
-					$this->created($node);
227
-				} else {
228
-					// Normally this should not happen so we re-throw the exception to not hide any potential issues.
229
-					throw $e;
230
-				}
231
-			} catch (Exception $e) {
232
-				$this->logger->error('Failed to update existing version for ' . $node->getPath(), [
233
-					'exception' => $e,
234
-					'versionCreated' => $writeHookInfo['versionCreated'],
235
-					'previousNode' => [
236
-						'size' => $writeHookInfo['previousNode']->getSize(),
237
-						'mtime' => $writeHookInfo['previousNode']->getMTime(),
238
-					],
239
-					'node' => [
240
-						'size' => $node->getSize(),
241
-						'mtime' => $node->getMTime(),
242
-					]
243
-				]);
244
-				throw $e;
245
-			}
246
-		}
247
-
248
-		unset($this->writeHookInfo[$node->getId()]);
249
-	}
250
-
251
-	/**
252
-	 * Erase versions of deleted file
253
-	 *
254
-	 * This function is connected to the delete signal of OC_Filesystem
255
-	 * cleanup the versions directory if the actual file gets deleted
256
-	 */
257
-	public function remove_hook(Node $node): void {
258
-		// Need to normalize the path as there is an issue with path concatenation in View.php::getAbsolutePath.
259
-		$path = Filesystem::normalizePath($node->getPath());
260
-		if (!array_key_exists($path, $this->versionsDeleted)) {
261
-			return;
262
-		}
263
-		$node = $this->versionsDeleted[$path];
264
-		$relativePath = $this->getPathForNode($node);
265
-		unset($this->versionsDeleted[$path]);
266
-		Storage::delete($relativePath);
267
-		// If no new version was stored in the FS, no new version should be added in the DB.
268
-		// So we simply update the associated version.
269
-		if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
270
-			$this->versionManager->deleteVersionsEntity($node);
271
-		}
272
-	}
273
-
274
-	/**
275
-	 * mark file as "deleted" so that we can clean up the versions if the file is gone
276
-	 */
277
-	public function pre_remove_hook(Node $node): void {
278
-		$path = $this->getPathForNode($node);
279
-		Storage::markDeletedFile($path);
280
-		$this->versionsDeleted[$node->getPath()] = $node;
281
-	}
282
-
283
-	/**
284
-	 * rename/move versions of renamed/moved files
285
-	 *
286
-	 * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
287
-	 * of the stored versions along the actual file
288
-	 */
289
-	public function rename_hook(Node $source, Node $target): void {
290
-		$sourceBackend = $this->versionManager->getBackendForStorage($source->getParent()->getStorage());
291
-		$targetBackend = $this->versionManager->getBackendForStorage($target->getStorage());
292
-		// If different backends, do nothing.
293
-		if ($sourceBackend !== $targetBackend) {
294
-			return;
295
-		}
296
-
297
-		$oldPath = $this->getPathForNode($source);
298
-		$newPath = $this->getPathForNode($target);
299
-		Storage::renameOrCopy($oldPath, $newPath, 'rename');
300
-	}
301
-
302
-	/**
303
-	 * copy versions of copied files
304
-	 *
305
-	 * This function is connected to the copy signal of OC_Filesystem and copies the
306
-	 * the stored versions to the new location
307
-	 */
308
-	public function copy_hook(Node $source, Node $target): void {
309
-		$sourceBackend = $this->versionManager->getBackendForStorage($source->getParent()->getStorage());
310
-		$targetBackend = $this->versionManager->getBackendForStorage($target->getStorage());
311
-		// If different backends, do nothing.
312
-		if ($sourceBackend !== $targetBackend) {
313
-			return;
314
-		}
315
-
316
-		$oldPath = $this->getPathForNode($source);
317
-		$newPath = $this->getPathForNode($target);
318
-		Storage::renameOrCopy($oldPath, $newPath, 'copy');
319
-	}
320
-
321
-	/**
322
-	 * Remember owner and the owner path of the source file.
323
-	 * If the file already exists, then it was a upload of a existing file
324
-	 * over the web interface and we call Storage::store() directly
325
-	 *
326
-	 *
327
-	 */
328
-	public function pre_renameOrCopy_hook(Node $source, Node $target): void {
329
-		$sourceBackend = $this->versionManager->getBackendForStorage($source->getStorage());
330
-		$targetBackend = $this->versionManager->getBackendForStorage($target->getParent()->getStorage());
331
-		// If different backends, do nothing.
332
-		if ($sourceBackend !== $targetBackend) {
333
-			return;
334
-		}
335
-
336
-		// if we rename a movable mount point, then the versions don't have to be renamed
337
-		$oldPath = $this->getPathForNode($source);
338
-		$newPath = $this->getPathForNode($target);
339
-		if ($oldPath === null || $newPath === null) {
340
-			return;
341
-		}
342
-
343
-		$user = $this->userSession->getUser()?->getUID();
344
-		if ($user === null) {
345
-			return;
346
-		}
347
-
348
-		$absOldPath = Filesystem::normalizePath('/' . $user . '/files' . $oldPath);
349
-		$manager = Filesystem::getMountManager();
350
-		$mount = $manager->find($absOldPath);
351
-		$internalPath = $mount->getInternalPath($absOldPath);
352
-		if ($internalPath === '' and $mount instanceof MoveableMount) {
353
-			return;
354
-		}
355
-
356
-		$view = new View($user . '/files');
357
-		if ($view->file_exists($newPath)) {
358
-			Storage::store($newPath);
359
-		} else {
360
-			Storage::setSourcePathAndUser($oldPath);
361
-		}
362
-	}
363
-
364
-	/**
365
-	 * Retrieve the path relative to the current user root folder.
366
-	 * If no user is connected, try to use the node's owner.
367
-	 */
368
-	private function getPathForNode(Node $node): ?string {
369
-		$user = $this->userSession->getUser()?->getUID();
370
-		if ($user) {
371
-			$path = $this->rootFolder
372
-				->getUserFolder($user)
373
-				->getRelativePath($node->getPath());
374
-
375
-			if ($path !== null) {
376
-				return $path;
377
-			}
378
-		}
379
-
380
-		try {
381
-			$owner = $node->getOwner()?->getUid();
382
-		} catch (NotFoundException) {
383
-			$owner = null;
384
-		}
385
-
386
-		// If no owner, extract it from the path.
387
-		// e.g. /user/files/foobar.txt
388
-		if (!$owner) {
389
-			$parts = explode('/', $node->getPath(), 4);
390
-			if (count($parts) === 4) {
391
-				$owner = $parts[1];
392
-			}
393
-		}
394
-
395
-		if ($owner) {
396
-			$path = $this->rootFolder
397
-				->getUserFolder($owner)
398
-				->getRelativePath($node->getPath());
399
-
400
-			if ($path !== null) {
401
-				return $path;
402
-			}
403
-		}
404
-
405
-		return null;
406
-	}
45
+    /**
46
+     * @var array<int, array>
47
+     */
48
+    private array $writeHookInfo = [];
49
+    /**
50
+     * @var array<int, Node>
51
+     */
52
+    private array $nodesTouched = [];
53
+    /**
54
+     * @var array<string, Node>
55
+     */
56
+    private array $versionsDeleted = [];
57
+
58
+    public function __construct(
59
+        private IRootFolder $rootFolder,
60
+        private IVersionManager $versionManager,
61
+        private IMimeTypeLoader $mimeTypeLoader,
62
+        private IUserSession $userSession,
63
+        private LoggerInterface $logger,
64
+    ) {
65
+    }
66
+
67
+    public function handle(Event $event): void {
68
+        if ($event instanceof NodeCreatedEvent) {
69
+            $this->created($event->getNode());
70
+        }
71
+
72
+        if ($event instanceof BeforeNodeTouchedEvent) {
73
+            $this->pre_touch_hook($event->getNode());
74
+        }
75
+
76
+        if ($event instanceof NodeTouchedEvent) {
77
+            $this->touch_hook($event->getNode());
78
+        }
79
+
80
+        if ($event instanceof BeforeNodeWrittenEvent) {
81
+            $this->write_hook($event->getNode());
82
+        }
83
+
84
+        if ($event instanceof NodeWrittenEvent) {
85
+            $this->post_write_hook($event->getNode());
86
+        }
87
+
88
+        if ($event instanceof BeforeNodeDeletedEvent) {
89
+            $this->pre_remove_hook($event->getNode());
90
+        }
91
+
92
+        if ($event instanceof NodeDeletedEvent) {
93
+            $this->remove_hook($event->getNode());
94
+        }
95
+
96
+        if ($event instanceof NodeRenamedEvent) {
97
+            $this->rename_hook($event->getSource(), $event->getTarget());
98
+        }
99
+
100
+        if ($event instanceof NodeCopiedEvent) {
101
+            $this->copy_hook($event->getSource(), $event->getTarget());
102
+        }
103
+
104
+        if ($event instanceof BeforeNodeRenamedEvent) {
105
+            $this->pre_renameOrCopy_hook($event->getSource(), $event->getTarget());
106
+        }
107
+
108
+        if ($event instanceof BeforeNodeCopiedEvent) {
109
+            $this->pre_renameOrCopy_hook($event->getSource(), $event->getTarget());
110
+        }
111
+    }
112
+
113
+    public function pre_touch_hook(Node $node): void {
114
+        // Do not handle folders.
115
+        if ($node instanceof Folder) {
116
+            return;
117
+        }
118
+
119
+        // $node is a non-existing on file creation.
120
+        if ($node instanceof NonExistingFile) {
121
+            return;
122
+        }
123
+
124
+        $this->nodesTouched[$node->getId()] = $node;
125
+    }
126
+
127
+    public function touch_hook(Node $node): void {
128
+        $previousNode = $this->nodesTouched[$node->getId()] ?? null;
129
+
130
+        if ($previousNode === null) {
131
+            return;
132
+        }
133
+
134
+        unset($this->nodesTouched[$node->getId()]);
135
+
136
+        try {
137
+            if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
138
+                // We update the timestamp of the version entity associated with the previousNode.
139
+                $this->versionManager->updateVersionEntity($node, $previousNode->getMTime(), ['timestamp' => $node->getMTime()]);
140
+            }
141
+        } catch (DbalException $ex) {
142
+            // Ignore UniqueConstraintViolationException, as we are probably in the middle of a rollback
143
+            // Where the previous node would temporary have the mtime of the old version, so the rollback touches it to fix it.
144
+            if (!($ex->getPrevious() instanceof UniqueConstraintViolationException)) {
145
+                throw $ex;
146
+            }
147
+        } catch (DoesNotExistException $ex) {
148
+            // Ignore DoesNotExistException, as we are probably in the middle of a rollback
149
+            // Where the previous node would temporary have a wrong mtime, so the rollback touches it to fix it.
150
+        }
151
+    }
152
+
153
+    public function created(Node $node): void {
154
+        // Do not handle folders.
155
+        if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
156
+            $this->versionManager->createVersionEntity($node);
157
+        }
158
+    }
159
+
160
+    /**
161
+     * listen to write event.
162
+     */
163
+    public function write_hook(Node $node): void {
164
+        // Do not handle folders.
165
+        if ($node instanceof Folder) {
166
+            return;
167
+        }
168
+
169
+        // $node is a non-existing on file creation.
170
+        if ($node instanceof NonExistingFile) {
171
+            return;
172
+        }
173
+
174
+        $path = $this->getPathForNode($node);
175
+        $result = Storage::store($path);
176
+
177
+        // Store the result of the version creation so it can be used in post_write_hook.
178
+        $this->writeHookInfo[$node->getId()] = [
179
+            'previousNode' => $node,
180
+            'versionCreated' => $result !== false
181
+        ];
182
+    }
183
+
184
+    /**
185
+     * listen to post_write event.
186
+     */
187
+    public function post_write_hook(Node $node): void {
188
+        // Do not handle folders.
189
+        if ($node instanceof Folder) {
190
+            return;
191
+        }
192
+
193
+        $writeHookInfo = $this->writeHookInfo[$node->getId()] ?? null;
194
+
195
+        if ($writeHookInfo === null) {
196
+            return;
197
+        }
198
+
199
+        if (
200
+            $writeHookInfo['versionCreated']
201
+            && $node->getMTime() !== $writeHookInfo['previousNode']->getMTime()
202
+        ) {
203
+            // If a new version was created, insert a version in the DB for the current content.
204
+            // If both versions have the same mtime, it means the latest version file simply got overrode,
205
+            // so no need to create a new version.
206
+            $this->created($node);
207
+        } else {
208
+            try {
209
+                // If no new version was stored in the FS, no new version should be added in the DB.
210
+                // So we simply update the associated version.
211
+                if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
212
+                    $this->versionManager->updateVersionEntity(
213
+                        $node,
214
+                        $writeHookInfo['previousNode']->getMtime(),
215
+                        [
216
+                            'timestamp' => $node->getMTime(),
217
+                            'size' => $node->getSize(),
218
+                            'mimetype' => $this->mimeTypeLoader->getId($node->getMimetype()),
219
+                        ],
220
+                    );
221
+                }
222
+            } catch (DoesNotExistException $e) {
223
+                // This happens if the versions app was not enabled while the file was created or updated the last time.
224
+                // meaning there is no such revision and we need to create this file.
225
+                if ($writeHookInfo['versionCreated']) {
226
+                    $this->created($node);
227
+                } else {
228
+                    // Normally this should not happen so we re-throw the exception to not hide any potential issues.
229
+                    throw $e;
230
+                }
231
+            } catch (Exception $e) {
232
+                $this->logger->error('Failed to update existing version for ' . $node->getPath(), [
233
+                    'exception' => $e,
234
+                    'versionCreated' => $writeHookInfo['versionCreated'],
235
+                    'previousNode' => [
236
+                        'size' => $writeHookInfo['previousNode']->getSize(),
237
+                        'mtime' => $writeHookInfo['previousNode']->getMTime(),
238
+                    ],
239
+                    'node' => [
240
+                        'size' => $node->getSize(),
241
+                        'mtime' => $node->getMTime(),
242
+                    ]
243
+                ]);
244
+                throw $e;
245
+            }
246
+        }
247
+
248
+        unset($this->writeHookInfo[$node->getId()]);
249
+    }
250
+
251
+    /**
252
+     * Erase versions of deleted file
253
+     *
254
+     * This function is connected to the delete signal of OC_Filesystem
255
+     * cleanup the versions directory if the actual file gets deleted
256
+     */
257
+    public function remove_hook(Node $node): void {
258
+        // Need to normalize the path as there is an issue with path concatenation in View.php::getAbsolutePath.
259
+        $path = Filesystem::normalizePath($node->getPath());
260
+        if (!array_key_exists($path, $this->versionsDeleted)) {
261
+            return;
262
+        }
263
+        $node = $this->versionsDeleted[$path];
264
+        $relativePath = $this->getPathForNode($node);
265
+        unset($this->versionsDeleted[$path]);
266
+        Storage::delete($relativePath);
267
+        // If no new version was stored in the FS, no new version should be added in the DB.
268
+        // So we simply update the associated version.
269
+        if ($node instanceof File && $this->versionManager instanceof INeedSyncVersionBackend) {
270
+            $this->versionManager->deleteVersionsEntity($node);
271
+        }
272
+    }
273
+
274
+    /**
275
+     * mark file as "deleted" so that we can clean up the versions if the file is gone
276
+     */
277
+    public function pre_remove_hook(Node $node): void {
278
+        $path = $this->getPathForNode($node);
279
+        Storage::markDeletedFile($path);
280
+        $this->versionsDeleted[$node->getPath()] = $node;
281
+    }
282
+
283
+    /**
284
+     * rename/move versions of renamed/moved files
285
+     *
286
+     * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
287
+     * of the stored versions along the actual file
288
+     */
289
+    public function rename_hook(Node $source, Node $target): void {
290
+        $sourceBackend = $this->versionManager->getBackendForStorage($source->getParent()->getStorage());
291
+        $targetBackend = $this->versionManager->getBackendForStorage($target->getStorage());
292
+        // If different backends, do nothing.
293
+        if ($sourceBackend !== $targetBackend) {
294
+            return;
295
+        }
296
+
297
+        $oldPath = $this->getPathForNode($source);
298
+        $newPath = $this->getPathForNode($target);
299
+        Storage::renameOrCopy($oldPath, $newPath, 'rename');
300
+    }
301
+
302
+    /**
303
+     * copy versions of copied files
304
+     *
305
+     * This function is connected to the copy signal of OC_Filesystem and copies the
306
+     * the stored versions to the new location
307
+     */
308
+    public function copy_hook(Node $source, Node $target): void {
309
+        $sourceBackend = $this->versionManager->getBackendForStorage($source->getParent()->getStorage());
310
+        $targetBackend = $this->versionManager->getBackendForStorage($target->getStorage());
311
+        // If different backends, do nothing.
312
+        if ($sourceBackend !== $targetBackend) {
313
+            return;
314
+        }
315
+
316
+        $oldPath = $this->getPathForNode($source);
317
+        $newPath = $this->getPathForNode($target);
318
+        Storage::renameOrCopy($oldPath, $newPath, 'copy');
319
+    }
320
+
321
+    /**
322
+     * Remember owner and the owner path of the source file.
323
+     * If the file already exists, then it was a upload of a existing file
324
+     * over the web interface and we call Storage::store() directly
325
+     *
326
+     *
327
+     */
328
+    public function pre_renameOrCopy_hook(Node $source, Node $target): void {
329
+        $sourceBackend = $this->versionManager->getBackendForStorage($source->getStorage());
330
+        $targetBackend = $this->versionManager->getBackendForStorage($target->getParent()->getStorage());
331
+        // If different backends, do nothing.
332
+        if ($sourceBackend !== $targetBackend) {
333
+            return;
334
+        }
335
+
336
+        // if we rename a movable mount point, then the versions don't have to be renamed
337
+        $oldPath = $this->getPathForNode($source);
338
+        $newPath = $this->getPathForNode($target);
339
+        if ($oldPath === null || $newPath === null) {
340
+            return;
341
+        }
342
+
343
+        $user = $this->userSession->getUser()?->getUID();
344
+        if ($user === null) {
345
+            return;
346
+        }
347
+
348
+        $absOldPath = Filesystem::normalizePath('/' . $user . '/files' . $oldPath);
349
+        $manager = Filesystem::getMountManager();
350
+        $mount = $manager->find($absOldPath);
351
+        $internalPath = $mount->getInternalPath($absOldPath);
352
+        if ($internalPath === '' and $mount instanceof MoveableMount) {
353
+            return;
354
+        }
355
+
356
+        $view = new View($user . '/files');
357
+        if ($view->file_exists($newPath)) {
358
+            Storage::store($newPath);
359
+        } else {
360
+            Storage::setSourcePathAndUser($oldPath);
361
+        }
362
+    }
363
+
364
+    /**
365
+     * Retrieve the path relative to the current user root folder.
366
+     * If no user is connected, try to use the node's owner.
367
+     */
368
+    private function getPathForNode(Node $node): ?string {
369
+        $user = $this->userSession->getUser()?->getUID();
370
+        if ($user) {
371
+            $path = $this->rootFolder
372
+                ->getUserFolder($user)
373
+                ->getRelativePath($node->getPath());
374
+
375
+            if ($path !== null) {
376
+                return $path;
377
+            }
378
+        }
379
+
380
+        try {
381
+            $owner = $node->getOwner()?->getUid();
382
+        } catch (NotFoundException) {
383
+            $owner = null;
384
+        }
385
+
386
+        // If no owner, extract it from the path.
387
+        // e.g. /user/files/foobar.txt
388
+        if (!$owner) {
389
+            $parts = explode('/', $node->getPath(), 4);
390
+            if (count($parts) === 4) {
391
+                $owner = $parts[1];
392
+            }
393
+        }
394
+
395
+        if ($owner) {
396
+            $path = $this->rootFolder
397
+                ->getUserFolder($owner)
398
+                ->getRelativePath($node->getPath());
399
+
400
+            if ($path !== null) {
401
+                return $path;
402
+            }
403
+        }
404
+
405
+        return null;
406
+    }
407 407
 }
Please login to merge, or discard this patch.
apps/files_versions/tests/VersioningTest.php 2 patches
Indentation   +871 added lines, -871 removed lines patch added patch discarded remove patch
@@ -36,960 +36,960 @@
 block discarded – undo
36 36
  * @group DB
37 37
  */
38 38
 class VersioningTest extends \Test\TestCase {
39
-	public const TEST_VERSIONS_USER = 'test-versions-user';
40
-	public const TEST_VERSIONS_USER2 = 'test-versions-user2';
41
-	public const USERS_VERSIONS_ROOT = '/test-versions-user/files_versions';
42
-
43
-	/**
44
-	 * @var View
45
-	 */
46
-	private $rootView;
47
-	/**
48
-	 * @var VersionsMapper
49
-	 */
50
-	private $versionsMapper;
51
-	/**
52
-	 * @var IMimeTypeLoader
53
-	 */
54
-	private $mimeTypeLoader;
55
-	private $user1;
56
-	private $user2;
57
-
58
-	public static function setUpBeforeClass(): void {
59
-		parent::setUpBeforeClass();
60
-
61
-		$application = new Application();
62
-
63
-		// create test user
64
-		self::loginHelper(self::TEST_VERSIONS_USER2, true);
65
-		self::loginHelper(self::TEST_VERSIONS_USER, true);
66
-	}
67
-
68
-	public static function tearDownAfterClass(): void {
69
-		// cleanup test user
70
-		$user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER);
71
-		if ($user !== null) {
72
-			$user->delete();
73
-		}
74
-		$user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER2);
75
-		if ($user !== null) {
76
-			$user->delete();
77
-		}
78
-
79
-		parent::tearDownAfterClass();
80
-	}
81
-
82
-	protected function setUp(): void {
83
-		parent::setUp();
84
-
85
-		$config = Server::get(IConfig::class);
86
-		$mockConfig = $this->createMock(IConfig::class);
87
-		$mockConfig->expects($this->any())
88
-			->method('getSystemValue')
89
-			->willReturnCallback(function ($key, $default) use ($config) {
90
-				if ($key === 'filesystem_check_changes') {
91
-					return Watcher::CHECK_ONCE;
92
-				} else {
93
-					return $config->getSystemValue($key, $default);
94
-				}
95
-			});
96
-		$this->overwriteService(AllConfig::class, $mockConfig);
97
-
98
-		// clear hooks
99
-		\OC_Hook::clear();
100
-		\OC::registerShareHooks(Server::get(SystemConfig::class));
101
-		\OC::$server->boot();
102
-
103
-		self::loginHelper(self::TEST_VERSIONS_USER);
104
-		$this->rootView = new View();
105
-		if (!$this->rootView->file_exists(self::USERS_VERSIONS_ROOT)) {
106
-			$this->rootView->mkdir(self::USERS_VERSIONS_ROOT);
107
-		}
108
-
109
-		$this->versionsMapper = Server::get(VersionsMapper::class);
110
-		$this->mimeTypeLoader = Server::get(IMimeTypeLoader::class);
111
-
112
-		$this->user1 = $this->createMock(IUser::class);
113
-		$this->user1->method('getUID')
114
-			->willReturn(self::TEST_VERSIONS_USER);
115
-		$this->user2 = $this->createMock(IUser::class);
116
-		$this->user2->method('getUID')
117
-			->willReturn(self::TEST_VERSIONS_USER2);
118
-	}
119
-
120
-	protected function tearDown(): void {
121
-		$this->restoreService(AllConfig::class);
122
-
123
-		if ($this->rootView) {
124
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files/');
125
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files/');
126
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files_versions/');
127
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files_versions/');
128
-		}
129
-
130
-		\OC_Hook::clear();
131
-
132
-		parent::tearDown();
133
-	}
134
-
135
-	/**
136
-	 * @medium
137
-	 * test expire logic
138
-	 * @dataProvider versionsProvider
139
-	 */
140
-	public function testGetExpireList($versions, $sizeOfAllDeletedFiles): void {
141
-
142
-		// last interval end at 2592000
143
-		$startTime = 5000000;
144
-
145
-		$testClass = new VersionStorageToTest();
146
-		[$deleted, $size] = $testClass->callProtectedGetExpireList($startTime, $versions);
147
-
148
-		// we should have deleted 16 files each of the size 1
149
-		$this->assertEquals($sizeOfAllDeletedFiles, $size);
150
-
151
-		// the deleted array should only contain versions which should be deleted
152
-		foreach ($deleted as $key => $path) {
153
-			unset($versions[$key]);
154
-			$this->assertEquals('delete', substr($path, 0, strlen('delete')));
155
-		}
156
-
157
-		// the versions array should only contain versions which should be kept
158
-		foreach ($versions as $version) {
159
-			$this->assertEquals('keep', $version['path']);
160
-		}
161
-	}
162
-
163
-	public function versionsProvider() {
164
-		return [
165
-			// first set of versions uniformly distributed versions
166
-			[
167
-				[
168
-					// first slice (10sec) keep one version every 2 seconds
169
-					['version' => 4999999, 'path' => 'keep', 'size' => 1],
170
-					['version' => 4999998, 'path' => 'delete', 'size' => 1],
171
-					['version' => 4999997, 'path' => 'keep', 'size' => 1],
172
-					['version' => 4999995, 'path' => 'keep', 'size' => 1],
173
-					['version' => 4999994, 'path' => 'delete', 'size' => 1],
174
-					//next slice (60sec) starts at 4999990 keep one version every 10 secons
175
-					['version' => 4999988, 'path' => 'keep', 'size' => 1],
176
-					['version' => 4999978, 'path' => 'keep', 'size' => 1],
177
-					['version' => 4999975, 'path' => 'delete', 'size' => 1],
178
-					['version' => 4999972, 'path' => 'delete', 'size' => 1],
179
-					['version' => 4999967, 'path' => 'keep', 'size' => 1],
180
-					['version' => 4999958, 'path' => 'delete', 'size' => 1],
181
-					['version' => 4999957, 'path' => 'keep', 'size' => 1],
182
-					//next slice (3600sec) start at 4999940 keep one version every 60 seconds
183
-					['version' => 4999900, 'path' => 'keep', 'size' => 1],
184
-					['version' => 4999841, 'path' => 'delete', 'size' => 1],
185
-					['version' => 4999840, 'path' => 'keep', 'size' => 1],
186
-					['version' => 4999780, 'path' => 'keep', 'size' => 1],
187
-					['version' => 4996401, 'path' => 'keep', 'size' => 1],
188
-					// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
189
-					['version' => 4996350, 'path' => 'delete', 'size' => 1],
190
-					['version' => 4992800, 'path' => 'keep', 'size' => 1],
191
-					['version' => 4989800, 'path' => 'delete', 'size' => 1],
192
-					['version' => 4989700, 'path' => 'delete', 'size' => 1],
193
-					['version' => 4989200, 'path' => 'keep', 'size' => 1],
194
-					// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
195
-					['version' => 4913600, 'path' => 'keep', 'size' => 1],
196
-					['version' => 4852800, 'path' => 'delete', 'size' => 1],
197
-					['version' => 4827201, 'path' => 'delete', 'size' => 1],
198
-					['version' => 4827200, 'path' => 'keep', 'size' => 1],
199
-					['version' => 4777201, 'path' => 'delete', 'size' => 1],
200
-					['version' => 4777501, 'path' => 'delete', 'size' => 1],
201
-					['version' => 4740000, 'path' => 'keep', 'size' => 1],
202
-					// final slice starts at 2408000 keep one version every 604800 secons
203
-					['version' => 2408000, 'path' => 'keep', 'size' => 1],
204
-					['version' => 1803201, 'path' => 'delete', 'size' => 1],
205
-					['version' => 1803200, 'path' => 'keep', 'size' => 1],
206
-					['version' => 1800199, 'path' => 'delete', 'size' => 1],
207
-					['version' => 1800100, 'path' => 'delete', 'size' => 1],
208
-					['version' => 1198300, 'path' => 'keep', 'size' => 1],
209
-				],
210
-				16 // size of all deleted files (every file has the size 1)
211
-			],
212
-			// second set of versions, here we have only really old versions
213
-			[
214
-				[
215
-					// first slice (10sec) keep one version every 2 seconds
216
-					// next slice (60sec) starts at 4999990 keep one version every 10 secons
217
-					// next slice (3600sec) start at 4999940 keep one version every 60 seconds
218
-					// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
219
-					['version' => 4996400, 'path' => 'keep', 'size' => 1],
220
-					['version' => 4996350, 'path' => 'delete', 'size' => 1],
221
-					['version' => 4996350, 'path' => 'delete', 'size' => 1],
222
-					['version' => 4992800, 'path' => 'keep', 'size' => 1],
223
-					['version' => 4989800, 'path' => 'delete', 'size' => 1],
224
-					['version' => 4989700, 'path' => 'delete', 'size' => 1],
225
-					['version' => 4989200, 'path' => 'keep', 'size' => 1],
226
-					// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
227
-					['version' => 4913600, 'path' => 'keep', 'size' => 1],
228
-					['version' => 4852800, 'path' => 'delete', 'size' => 1],
229
-					['version' => 4827201, 'path' => 'delete', 'size' => 1],
230
-					['version' => 4827200, 'path' => 'keep', 'size' => 1],
231
-					['version' => 4777201, 'path' => 'delete', 'size' => 1],
232
-					['version' => 4777501, 'path' => 'delete', 'size' => 1],
233
-					['version' => 4740000, 'path' => 'keep', 'size' => 1],
234
-					// final slice starts at 2408000 keep one version every 604800 secons
235
-					['version' => 2408000, 'path' => 'keep', 'size' => 1],
236
-					['version' => 1803201, 'path' => 'delete', 'size' => 1],
237
-					['version' => 1803200, 'path' => 'keep', 'size' => 1],
238
-					['version' => 1800199, 'path' => 'delete', 'size' => 1],
239
-					['version' => 1800100, 'path' => 'delete', 'size' => 1],
240
-					['version' => 1198300, 'path' => 'keep', 'size' => 1],
241
-				],
242
-				11 // size of all deleted files (every file has the size 1)
243
-			],
244
-			// third set of versions, with some gaps between
245
-			[
246
-				[
247
-					// first slice (10sec) keep one version every 2 seconds
248
-					['version' => 4999999, 'path' => 'keep', 'size' => 1],
249
-					['version' => 4999998, 'path' => 'delete', 'size' => 1],
250
-					['version' => 4999997, 'path' => 'keep', 'size' => 1],
251
-					['version' => 4999995, 'path' => 'keep', 'size' => 1],
252
-					['version' => 4999994, 'path' => 'delete', 'size' => 1],
253
-					//next slice (60sec) starts at 4999990 keep one version every 10 secons
254
-					['version' => 4999988, 'path' => 'keep', 'size' => 1],
255
-					['version' => 4999978, 'path' => 'keep', 'size' => 1],
256
-					//next slice (3600sec) start at 4999940 keep one version every 60 seconds
257
-					// next slice (86400sec) start at 4996400 keep one version every 3600 seconds
258
-					['version' => 4989200, 'path' => 'keep', 'size' => 1],
259
-					// next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
260
-					['version' => 4913600, 'path' => 'keep', 'size' => 1],
261
-					['version' => 4852800, 'path' => 'delete', 'size' => 1],
262
-					['version' => 4827201, 'path' => 'delete', 'size' => 1],
263
-					['version' => 4827200, 'path' => 'keep', 'size' => 1],
264
-					['version' => 4777201, 'path' => 'delete', 'size' => 1],
265
-					['version' => 4777501, 'path' => 'delete', 'size' => 1],
266
-					['version' => 4740000, 'path' => 'keep', 'size' => 1],
267
-					// final slice starts at 2408000 keep one version every 604800 secons
268
-					['version' => 2408000, 'path' => 'keep', 'size' => 1],
269
-					['version' => 1803201, 'path' => 'delete', 'size' => 1],
270
-					['version' => 1803200, 'path' => 'keep', 'size' => 1],
271
-					['version' => 1800199, 'path' => 'delete', 'size' => 1],
272
-					['version' => 1800100, 'path' => 'delete', 'size' => 1],
273
-					['version' => 1198300, 'path' => 'keep', 'size' => 1],
274
-				],
275
-				9 // size of all deleted files (every file has the size 1)
276
-			],
277
-			// fourth set of versions: empty (see issue #19066)
278
-			[
279
-				[],
280
-				0
281
-			]
282
-
283
-		];
284
-	}
285
-
286
-	public function testRename(): void {
287
-		Filesystem::file_put_contents('test.txt', 'test file');
288
-
289
-		$t1 = time();
290
-		// second version is two weeks older, this way we make sure that no
291
-		// version will be expired
292
-		$t2 = $t1 - 60 * 60 * 24 * 14;
293
-
294
-		// create some versions
295
-		$v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
296
-		$v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
297
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
298
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
299
-
300
-		$this->rootView->file_put_contents($v1, 'version1');
301
-		$this->rootView->file_put_contents($v2, 'version2');
302
-
303
-		// execute rename hook of versions app
304
-		Filesystem::rename('test.txt', 'test2.txt');
305
-
306
-		$this->runCommands();
307
-
308
-		$this->assertFalse($this->rootView->file_exists($v1), 'version 1 of old file does not exist');
309
-		$this->assertFalse($this->rootView->file_exists($v2), 'version 2 of old file does not exist');
310
-
311
-		$this->assertTrue($this->rootView->file_exists($v1Renamed), 'version 1 of renamed file exists');
312
-		$this->assertTrue($this->rootView->file_exists($v2Renamed), 'version 2 of renamed file exists');
313
-	}
314
-
315
-	public function testRenameInSharedFolder(): void {
316
-		Filesystem::mkdir('folder1');
317
-		Filesystem::mkdir('folder1/folder2');
318
-		Filesystem::file_put_contents('folder1/test.txt', 'test file');
319
-
320
-		$t1 = time();
321
-		// second version is two weeks older, this way we make sure that no
322
-		// version will be expired
323
-		$t2 = $t1 - 60 * 60 * 24 * 14;
324
-
325
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/folder1');
326
-		// create some versions
327
-		$v1 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t1;
328
-		$v2 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t2;
329
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/folder1/folder2/test.txt.v' . $t1;
330
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/folder1/folder2/test.txt.v' . $t2;
331
-
332
-		$this->rootView->file_put_contents($v1, 'version1');
333
-		$this->rootView->file_put_contents($v2, 'version2');
334
-
335
-		$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
336
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
337
-		$share->setNode($node)
338
-			->setShareType(IShare::TYPE_USER)
339
-			->setSharedBy(self::TEST_VERSIONS_USER)
340
-			->setSharedWith(self::TEST_VERSIONS_USER2)
341
-			->setPermissions(Constants::PERMISSION_ALL);
342
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
343
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
344
-
345
-		self::loginHelper(self::TEST_VERSIONS_USER2);
346
-
347
-		$this->assertTrue(Filesystem::file_exists('folder1/test.txt'));
348
-
349
-		// execute rename hook of versions app
350
-		Filesystem::rename('/folder1/test.txt', '/folder1/folder2/test.txt');
351
-
352
-		$this->runCommands();
353
-
354
-		self::loginHelper(self::TEST_VERSIONS_USER);
355
-
356
-		$this->assertFalse($this->rootView->file_exists($v1), 'version 1 of old file does not exist');
357
-		$this->assertFalse($this->rootView->file_exists($v2), 'version 2 of old file does not exist');
358
-
359
-		$this->assertTrue($this->rootView->file_exists($v1Renamed), 'version 1 of renamed file exists');
360
-		$this->assertTrue($this->rootView->file_exists($v2Renamed), 'version 2 of renamed file exists');
361
-
362
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
363
-	}
364
-
365
-	public function testMoveFolder(): void {
366
-		Filesystem::mkdir('folder1');
367
-		Filesystem::mkdir('folder2');
368
-		Filesystem::file_put_contents('folder1/test.txt', 'test file');
369
-
370
-		$t1 = time();
371
-		// second version is two weeks older, this way we make sure that no
372
-		// version will be expired
373
-		$t2 = $t1 - 60 * 60 * 24 * 14;
374
-
375
-		// create some versions
376
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/folder1');
377
-		$v1 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t1;
378
-		$v2 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t2;
379
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/folder2/folder1/test.txt.v' . $t1;
380
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/folder2/folder1/test.txt.v' . $t2;
39
+    public const TEST_VERSIONS_USER = 'test-versions-user';
40
+    public const TEST_VERSIONS_USER2 = 'test-versions-user2';
41
+    public const USERS_VERSIONS_ROOT = '/test-versions-user/files_versions';
42
+
43
+    /**
44
+     * @var View
45
+     */
46
+    private $rootView;
47
+    /**
48
+     * @var VersionsMapper
49
+     */
50
+    private $versionsMapper;
51
+    /**
52
+     * @var IMimeTypeLoader
53
+     */
54
+    private $mimeTypeLoader;
55
+    private $user1;
56
+    private $user2;
57
+
58
+    public static function setUpBeforeClass(): void {
59
+        parent::setUpBeforeClass();
60
+
61
+        $application = new Application();
62
+
63
+        // create test user
64
+        self::loginHelper(self::TEST_VERSIONS_USER2, true);
65
+        self::loginHelper(self::TEST_VERSIONS_USER, true);
66
+    }
67
+
68
+    public static function tearDownAfterClass(): void {
69
+        // cleanup test user
70
+        $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER);
71
+        if ($user !== null) {
72
+            $user->delete();
73
+        }
74
+        $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER2);
75
+        if ($user !== null) {
76
+            $user->delete();
77
+        }
78
+
79
+        parent::tearDownAfterClass();
80
+    }
81
+
82
+    protected function setUp(): void {
83
+        parent::setUp();
84
+
85
+        $config = Server::get(IConfig::class);
86
+        $mockConfig = $this->createMock(IConfig::class);
87
+        $mockConfig->expects($this->any())
88
+            ->method('getSystemValue')
89
+            ->willReturnCallback(function ($key, $default) use ($config) {
90
+                if ($key === 'filesystem_check_changes') {
91
+                    return Watcher::CHECK_ONCE;
92
+                } else {
93
+                    return $config->getSystemValue($key, $default);
94
+                }
95
+            });
96
+        $this->overwriteService(AllConfig::class, $mockConfig);
97
+
98
+        // clear hooks
99
+        \OC_Hook::clear();
100
+        \OC::registerShareHooks(Server::get(SystemConfig::class));
101
+        \OC::$server->boot();
102
+
103
+        self::loginHelper(self::TEST_VERSIONS_USER);
104
+        $this->rootView = new View();
105
+        if (!$this->rootView->file_exists(self::USERS_VERSIONS_ROOT)) {
106
+            $this->rootView->mkdir(self::USERS_VERSIONS_ROOT);
107
+        }
108
+
109
+        $this->versionsMapper = Server::get(VersionsMapper::class);
110
+        $this->mimeTypeLoader = Server::get(IMimeTypeLoader::class);
111
+
112
+        $this->user1 = $this->createMock(IUser::class);
113
+        $this->user1->method('getUID')
114
+            ->willReturn(self::TEST_VERSIONS_USER);
115
+        $this->user2 = $this->createMock(IUser::class);
116
+        $this->user2->method('getUID')
117
+            ->willReturn(self::TEST_VERSIONS_USER2);
118
+    }
119
+
120
+    protected function tearDown(): void {
121
+        $this->restoreService(AllConfig::class);
122
+
123
+        if ($this->rootView) {
124
+            $this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files/');
125
+            $this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files/');
126
+            $this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files_versions/');
127
+            $this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files_versions/');
128
+        }
129
+
130
+        \OC_Hook::clear();
131
+
132
+        parent::tearDown();
133
+    }
134
+
135
+    /**
136
+     * @medium
137
+     * test expire logic
138
+     * @dataProvider versionsProvider
139
+     */
140
+    public function testGetExpireList($versions, $sizeOfAllDeletedFiles): void {
141
+
142
+        // last interval end at 2592000
143
+        $startTime = 5000000;
144
+
145
+        $testClass = new VersionStorageToTest();
146
+        [$deleted, $size] = $testClass->callProtectedGetExpireList($startTime, $versions);
147
+
148
+        // we should have deleted 16 files each of the size 1
149
+        $this->assertEquals($sizeOfAllDeletedFiles, $size);
150
+
151
+        // the deleted array should only contain versions which should be deleted
152
+        foreach ($deleted as $key => $path) {
153
+            unset($versions[$key]);
154
+            $this->assertEquals('delete', substr($path, 0, strlen('delete')));
155
+        }
156
+
157
+        // the versions array should only contain versions which should be kept
158
+        foreach ($versions as $version) {
159
+            $this->assertEquals('keep', $version['path']);
160
+        }
161
+    }
162
+
163
+    public function versionsProvider() {
164
+        return [
165
+            // first set of versions uniformly distributed versions
166
+            [
167
+                [
168
+                    // first slice (10sec) keep one version every 2 seconds
169
+                    ['version' => 4999999, 'path' => 'keep', 'size' => 1],
170
+                    ['version' => 4999998, 'path' => 'delete', 'size' => 1],
171
+                    ['version' => 4999997, 'path' => 'keep', 'size' => 1],
172
+                    ['version' => 4999995, 'path' => 'keep', 'size' => 1],
173
+                    ['version' => 4999994, 'path' => 'delete', 'size' => 1],
174
+                    //next slice (60sec) starts at 4999990 keep one version every 10 secons
175
+                    ['version' => 4999988, 'path' => 'keep', 'size' => 1],
176
+                    ['version' => 4999978, 'path' => 'keep', 'size' => 1],
177
+                    ['version' => 4999975, 'path' => 'delete', 'size' => 1],
178
+                    ['version' => 4999972, 'path' => 'delete', 'size' => 1],
179
+                    ['version' => 4999967, 'path' => 'keep', 'size' => 1],
180
+                    ['version' => 4999958, 'path' => 'delete', 'size' => 1],
181
+                    ['version' => 4999957, 'path' => 'keep', 'size' => 1],
182
+                    //next slice (3600sec) start at 4999940 keep one version every 60 seconds
183
+                    ['version' => 4999900, 'path' => 'keep', 'size' => 1],
184
+                    ['version' => 4999841, 'path' => 'delete', 'size' => 1],
185
+                    ['version' => 4999840, 'path' => 'keep', 'size' => 1],
186
+                    ['version' => 4999780, 'path' => 'keep', 'size' => 1],
187
+                    ['version' => 4996401, 'path' => 'keep', 'size' => 1],
188
+                    // next slice (86400sec) start at 4996400 keep one version every 3600 seconds
189
+                    ['version' => 4996350, 'path' => 'delete', 'size' => 1],
190
+                    ['version' => 4992800, 'path' => 'keep', 'size' => 1],
191
+                    ['version' => 4989800, 'path' => 'delete', 'size' => 1],
192
+                    ['version' => 4989700, 'path' => 'delete', 'size' => 1],
193
+                    ['version' => 4989200, 'path' => 'keep', 'size' => 1],
194
+                    // next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
195
+                    ['version' => 4913600, 'path' => 'keep', 'size' => 1],
196
+                    ['version' => 4852800, 'path' => 'delete', 'size' => 1],
197
+                    ['version' => 4827201, 'path' => 'delete', 'size' => 1],
198
+                    ['version' => 4827200, 'path' => 'keep', 'size' => 1],
199
+                    ['version' => 4777201, 'path' => 'delete', 'size' => 1],
200
+                    ['version' => 4777501, 'path' => 'delete', 'size' => 1],
201
+                    ['version' => 4740000, 'path' => 'keep', 'size' => 1],
202
+                    // final slice starts at 2408000 keep one version every 604800 secons
203
+                    ['version' => 2408000, 'path' => 'keep', 'size' => 1],
204
+                    ['version' => 1803201, 'path' => 'delete', 'size' => 1],
205
+                    ['version' => 1803200, 'path' => 'keep', 'size' => 1],
206
+                    ['version' => 1800199, 'path' => 'delete', 'size' => 1],
207
+                    ['version' => 1800100, 'path' => 'delete', 'size' => 1],
208
+                    ['version' => 1198300, 'path' => 'keep', 'size' => 1],
209
+                ],
210
+                16 // size of all deleted files (every file has the size 1)
211
+            ],
212
+            // second set of versions, here we have only really old versions
213
+            [
214
+                [
215
+                    // first slice (10sec) keep one version every 2 seconds
216
+                    // next slice (60sec) starts at 4999990 keep one version every 10 secons
217
+                    // next slice (3600sec) start at 4999940 keep one version every 60 seconds
218
+                    // next slice (86400sec) start at 4996400 keep one version every 3600 seconds
219
+                    ['version' => 4996400, 'path' => 'keep', 'size' => 1],
220
+                    ['version' => 4996350, 'path' => 'delete', 'size' => 1],
221
+                    ['version' => 4996350, 'path' => 'delete', 'size' => 1],
222
+                    ['version' => 4992800, 'path' => 'keep', 'size' => 1],
223
+                    ['version' => 4989800, 'path' => 'delete', 'size' => 1],
224
+                    ['version' => 4989700, 'path' => 'delete', 'size' => 1],
225
+                    ['version' => 4989200, 'path' => 'keep', 'size' => 1],
226
+                    // next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
227
+                    ['version' => 4913600, 'path' => 'keep', 'size' => 1],
228
+                    ['version' => 4852800, 'path' => 'delete', 'size' => 1],
229
+                    ['version' => 4827201, 'path' => 'delete', 'size' => 1],
230
+                    ['version' => 4827200, 'path' => 'keep', 'size' => 1],
231
+                    ['version' => 4777201, 'path' => 'delete', 'size' => 1],
232
+                    ['version' => 4777501, 'path' => 'delete', 'size' => 1],
233
+                    ['version' => 4740000, 'path' => 'keep', 'size' => 1],
234
+                    // final slice starts at 2408000 keep one version every 604800 secons
235
+                    ['version' => 2408000, 'path' => 'keep', 'size' => 1],
236
+                    ['version' => 1803201, 'path' => 'delete', 'size' => 1],
237
+                    ['version' => 1803200, 'path' => 'keep', 'size' => 1],
238
+                    ['version' => 1800199, 'path' => 'delete', 'size' => 1],
239
+                    ['version' => 1800100, 'path' => 'delete', 'size' => 1],
240
+                    ['version' => 1198300, 'path' => 'keep', 'size' => 1],
241
+                ],
242
+                11 // size of all deleted files (every file has the size 1)
243
+            ],
244
+            // third set of versions, with some gaps between
245
+            [
246
+                [
247
+                    // first slice (10sec) keep one version every 2 seconds
248
+                    ['version' => 4999999, 'path' => 'keep', 'size' => 1],
249
+                    ['version' => 4999998, 'path' => 'delete', 'size' => 1],
250
+                    ['version' => 4999997, 'path' => 'keep', 'size' => 1],
251
+                    ['version' => 4999995, 'path' => 'keep', 'size' => 1],
252
+                    ['version' => 4999994, 'path' => 'delete', 'size' => 1],
253
+                    //next slice (60sec) starts at 4999990 keep one version every 10 secons
254
+                    ['version' => 4999988, 'path' => 'keep', 'size' => 1],
255
+                    ['version' => 4999978, 'path' => 'keep', 'size' => 1],
256
+                    //next slice (3600sec) start at 4999940 keep one version every 60 seconds
257
+                    // next slice (86400sec) start at 4996400 keep one version every 3600 seconds
258
+                    ['version' => 4989200, 'path' => 'keep', 'size' => 1],
259
+                    // next slice (2592000sec) start at 4913600 keep one version every 86400 seconds
260
+                    ['version' => 4913600, 'path' => 'keep', 'size' => 1],
261
+                    ['version' => 4852800, 'path' => 'delete', 'size' => 1],
262
+                    ['version' => 4827201, 'path' => 'delete', 'size' => 1],
263
+                    ['version' => 4827200, 'path' => 'keep', 'size' => 1],
264
+                    ['version' => 4777201, 'path' => 'delete', 'size' => 1],
265
+                    ['version' => 4777501, 'path' => 'delete', 'size' => 1],
266
+                    ['version' => 4740000, 'path' => 'keep', 'size' => 1],
267
+                    // final slice starts at 2408000 keep one version every 604800 secons
268
+                    ['version' => 2408000, 'path' => 'keep', 'size' => 1],
269
+                    ['version' => 1803201, 'path' => 'delete', 'size' => 1],
270
+                    ['version' => 1803200, 'path' => 'keep', 'size' => 1],
271
+                    ['version' => 1800199, 'path' => 'delete', 'size' => 1],
272
+                    ['version' => 1800100, 'path' => 'delete', 'size' => 1],
273
+                    ['version' => 1198300, 'path' => 'keep', 'size' => 1],
274
+                ],
275
+                9 // size of all deleted files (every file has the size 1)
276
+            ],
277
+            // fourth set of versions: empty (see issue #19066)
278
+            [
279
+                [],
280
+                0
281
+            ]
282
+
283
+        ];
284
+    }
285
+
286
+    public function testRename(): void {
287
+        Filesystem::file_put_contents('test.txt', 'test file');
288
+
289
+        $t1 = time();
290
+        // second version is two weeks older, this way we make sure that no
291
+        // version will be expired
292
+        $t2 = $t1 - 60 * 60 * 24 * 14;
293
+
294
+        // create some versions
295
+        $v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
296
+        $v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
297
+        $v1Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
298
+        $v2Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
299
+
300
+        $this->rootView->file_put_contents($v1, 'version1');
301
+        $this->rootView->file_put_contents($v2, 'version2');
302
+
303
+        // execute rename hook of versions app
304
+        Filesystem::rename('test.txt', 'test2.txt');
305
+
306
+        $this->runCommands();
307
+
308
+        $this->assertFalse($this->rootView->file_exists($v1), 'version 1 of old file does not exist');
309
+        $this->assertFalse($this->rootView->file_exists($v2), 'version 2 of old file does not exist');
310
+
311
+        $this->assertTrue($this->rootView->file_exists($v1Renamed), 'version 1 of renamed file exists');
312
+        $this->assertTrue($this->rootView->file_exists($v2Renamed), 'version 2 of renamed file exists');
313
+    }
314
+
315
+    public function testRenameInSharedFolder(): void {
316
+        Filesystem::mkdir('folder1');
317
+        Filesystem::mkdir('folder1/folder2');
318
+        Filesystem::file_put_contents('folder1/test.txt', 'test file');
319
+
320
+        $t1 = time();
321
+        // second version is two weeks older, this way we make sure that no
322
+        // version will be expired
323
+        $t2 = $t1 - 60 * 60 * 24 * 14;
324
+
325
+        $this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/folder1');
326
+        // create some versions
327
+        $v1 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t1;
328
+        $v2 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t2;
329
+        $v1Renamed = self::USERS_VERSIONS_ROOT . '/folder1/folder2/test.txt.v' . $t1;
330
+        $v2Renamed = self::USERS_VERSIONS_ROOT . '/folder1/folder2/test.txt.v' . $t2;
331
+
332
+        $this->rootView->file_put_contents($v1, 'version1');
333
+        $this->rootView->file_put_contents($v2, 'version2');
334
+
335
+        $node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
336
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
337
+        $share->setNode($node)
338
+            ->setShareType(IShare::TYPE_USER)
339
+            ->setSharedBy(self::TEST_VERSIONS_USER)
340
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
341
+            ->setPermissions(Constants::PERMISSION_ALL);
342
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
343
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
344
+
345
+        self::loginHelper(self::TEST_VERSIONS_USER2);
346
+
347
+        $this->assertTrue(Filesystem::file_exists('folder1/test.txt'));
348
+
349
+        // execute rename hook of versions app
350
+        Filesystem::rename('/folder1/test.txt', '/folder1/folder2/test.txt');
351
+
352
+        $this->runCommands();
353
+
354
+        self::loginHelper(self::TEST_VERSIONS_USER);
355
+
356
+        $this->assertFalse($this->rootView->file_exists($v1), 'version 1 of old file does not exist');
357
+        $this->assertFalse($this->rootView->file_exists($v2), 'version 2 of old file does not exist');
358
+
359
+        $this->assertTrue($this->rootView->file_exists($v1Renamed), 'version 1 of renamed file exists');
360
+        $this->assertTrue($this->rootView->file_exists($v2Renamed), 'version 2 of renamed file exists');
361
+
362
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
363
+    }
364
+
365
+    public function testMoveFolder(): void {
366
+        Filesystem::mkdir('folder1');
367
+        Filesystem::mkdir('folder2');
368
+        Filesystem::file_put_contents('folder1/test.txt', 'test file');
369
+
370
+        $t1 = time();
371
+        // second version is two weeks older, this way we make sure that no
372
+        // version will be expired
373
+        $t2 = $t1 - 60 * 60 * 24 * 14;
374
+
375
+        // create some versions
376
+        $this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/folder1');
377
+        $v1 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t1;
378
+        $v2 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t2;
379
+        $v1Renamed = self::USERS_VERSIONS_ROOT . '/folder2/folder1/test.txt.v' . $t1;
380
+        $v2Renamed = self::USERS_VERSIONS_ROOT . '/folder2/folder1/test.txt.v' . $t2;
381 381
 
382
-		$this->rootView->file_put_contents($v1, 'version1');
383
-		$this->rootView->file_put_contents($v2, 'version2');
382
+        $this->rootView->file_put_contents($v1, 'version1');
383
+        $this->rootView->file_put_contents($v2, 'version2');
384 384
 
385
-		// execute rename hook of versions app
386
-		Filesystem::rename('folder1', 'folder2/folder1');
385
+        // execute rename hook of versions app
386
+        Filesystem::rename('folder1', 'folder2/folder1');
387 387
 
388
-		$this->runCommands();
388
+        $this->runCommands();
389 389
 
390
-		$this->assertFalse($this->rootView->file_exists($v1));
391
-		$this->assertFalse($this->rootView->file_exists($v2));
390
+        $this->assertFalse($this->rootView->file_exists($v1));
391
+        $this->assertFalse($this->rootView->file_exists($v2));
392 392
 
393
-		$this->assertTrue($this->rootView->file_exists($v1Renamed));
394
-		$this->assertTrue($this->rootView->file_exists($v2Renamed));
395
-	}
393
+        $this->assertTrue($this->rootView->file_exists($v1Renamed));
394
+        $this->assertTrue($this->rootView->file_exists($v2Renamed));
395
+    }
396 396
 
397 397
 
398
-	public function testMoveFileIntoSharedFolderAsRecipient(): void {
399
-		Filesystem::mkdir('folder1');
400
-		$fileInfo = Filesystem::getFileInfo('folder1');
398
+    public function testMoveFileIntoSharedFolderAsRecipient(): void {
399
+        Filesystem::mkdir('folder1');
400
+        $fileInfo = Filesystem::getFileInfo('folder1');
401 401
 
402
-		$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
403
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
404
-		$share->setNode($node)
405
-			->setShareType(IShare::TYPE_USER)
406
-			->setSharedBy(self::TEST_VERSIONS_USER)
407
-			->setSharedWith(self::TEST_VERSIONS_USER2)
408
-			->setPermissions(Constants::PERMISSION_ALL);
409
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
410
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
402
+        $node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
403
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
404
+        $share->setNode($node)
405
+            ->setShareType(IShare::TYPE_USER)
406
+            ->setSharedBy(self::TEST_VERSIONS_USER)
407
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
408
+            ->setPermissions(Constants::PERMISSION_ALL);
409
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
410
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
411 411
 
412
-		self::loginHelper(self::TEST_VERSIONS_USER2);
413
-		$versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
414
-		Filesystem::file_put_contents('test.txt', 'test file');
412
+        self::loginHelper(self::TEST_VERSIONS_USER2);
413
+        $versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
414
+        Filesystem::file_put_contents('test.txt', 'test file');
415 415
 
416
-		$t1 = time();
417
-		// second version is two weeks older, this way we make sure that no
418
-		// version will be expired
419
-		$t2 = $t1 - 60 * 60 * 24 * 14;
416
+        $t1 = time();
417
+        // second version is two weeks older, this way we make sure that no
418
+        // version will be expired
419
+        $t2 = $t1 - 60 * 60 * 24 * 14;
420 420
 
421
-		$this->rootView->mkdir($versionsFolder2);
422
-		// create some versions
423
-		$v1 = $versionsFolder2 . '/test.txt.v' . $t1;
424
-		$v2 = $versionsFolder2 . '/test.txt.v' . $t2;
421
+        $this->rootView->mkdir($versionsFolder2);
422
+        // create some versions
423
+        $v1 = $versionsFolder2 . '/test.txt.v' . $t1;
424
+        $v2 = $versionsFolder2 . '/test.txt.v' . $t2;
425 425
 
426
-		$this->rootView->file_put_contents($v1, 'version1');
427
-		$this->rootView->file_put_contents($v2, 'version2');
426
+        $this->rootView->file_put_contents($v1, 'version1');
427
+        $this->rootView->file_put_contents($v2, 'version2');
428 428
 
429
-		// move file into the shared folder as recipient
430
-		Filesystem::rename('/test.txt', '/folder1/test.txt');
429
+        // move file into the shared folder as recipient
430
+        Filesystem::rename('/test.txt', '/folder1/test.txt');
431 431
 
432
-		$this->assertFalse($this->rootView->file_exists($v1));
433
-		$this->assertFalse($this->rootView->file_exists($v2));
432
+        $this->assertFalse($this->rootView->file_exists($v1));
433
+        $this->assertFalse($this->rootView->file_exists($v2));
434 434
 
435
-		self::loginHelper(self::TEST_VERSIONS_USER);
435
+        self::loginHelper(self::TEST_VERSIONS_USER);
436 436
 
437
-		$versionsFolder1 = '/' . self::TEST_VERSIONS_USER . '/files_versions';
437
+        $versionsFolder1 = '/' . self::TEST_VERSIONS_USER . '/files_versions';
438 438
 
439
-		$v1Renamed = $versionsFolder1 . '/folder1/test.txt.v' . $t1;
440
-		$v2Renamed = $versionsFolder1 . '/folder1/test.txt.v' . $t2;
439
+        $v1Renamed = $versionsFolder1 . '/folder1/test.txt.v' . $t1;
440
+        $v2Renamed = $versionsFolder1 . '/folder1/test.txt.v' . $t2;
441 441
 
442
-		$this->assertTrue($this->rootView->file_exists($v1Renamed));
443
-		$this->assertTrue($this->rootView->file_exists($v2Renamed));
442
+        $this->assertTrue($this->rootView->file_exists($v1Renamed));
443
+        $this->assertTrue($this->rootView->file_exists($v2Renamed));
444 444
 
445
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
446
-	}
445
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
446
+    }
447 447
 
448
-	public function testMoveFolderIntoSharedFolderAsRecipient(): void {
449
-		Filesystem::mkdir('folder1');
448
+    public function testMoveFolderIntoSharedFolderAsRecipient(): void {
449
+        Filesystem::mkdir('folder1');
450 450
 
451
-		$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
452
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
453
-		$share->setNode($node)
454
-			->setShareType(IShare::TYPE_USER)
455
-			->setSharedBy(self::TEST_VERSIONS_USER)
456
-			->setSharedWith(self::TEST_VERSIONS_USER2)
457
-			->setPermissions(Constants::PERMISSION_ALL);
458
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
459
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
451
+        $node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder1');
452
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
453
+        $share->setNode($node)
454
+            ->setShareType(IShare::TYPE_USER)
455
+            ->setSharedBy(self::TEST_VERSIONS_USER)
456
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
457
+            ->setPermissions(Constants::PERMISSION_ALL);
458
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
459
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
460 460
 
461
-		self::loginHelper(self::TEST_VERSIONS_USER2);
462
-		$versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
463
-		Filesystem::mkdir('folder2');
464
-		Filesystem::file_put_contents('folder2/test.txt', 'test file');
461
+        self::loginHelper(self::TEST_VERSIONS_USER2);
462
+        $versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
463
+        Filesystem::mkdir('folder2');
464
+        Filesystem::file_put_contents('folder2/test.txt', 'test file');
465 465
 
466
-		$t1 = time();
467
-		// second version is two weeks older, this way we make sure that no
468
-		// version will be expired
469
-		$t2 = $t1 - 60 * 60 * 24 * 14;
466
+        $t1 = time();
467
+        // second version is two weeks older, this way we make sure that no
468
+        // version will be expired
469
+        $t2 = $t1 - 60 * 60 * 24 * 14;
470 470
 
471
-		$this->rootView->mkdir($versionsFolder2);
472
-		$this->rootView->mkdir($versionsFolder2 . '/folder2');
473
-		// create some versions
474
-		$v1 = $versionsFolder2 . '/folder2/test.txt.v' . $t1;
475
-		$v2 = $versionsFolder2 . '/folder2/test.txt.v' . $t2;
471
+        $this->rootView->mkdir($versionsFolder2);
472
+        $this->rootView->mkdir($versionsFolder2 . '/folder2');
473
+        // create some versions
474
+        $v1 = $versionsFolder2 . '/folder2/test.txt.v' . $t1;
475
+        $v2 = $versionsFolder2 . '/folder2/test.txt.v' . $t2;
476 476
 
477
-		$this->rootView->file_put_contents($v1, 'version1');
478
-		$this->rootView->file_put_contents($v2, 'version2');
477
+        $this->rootView->file_put_contents($v1, 'version1');
478
+        $this->rootView->file_put_contents($v2, 'version2');
479 479
 
480
-		// move file into the shared folder as recipient
481
-		Filesystem::rename('/folder2', '/folder1/folder2');
480
+        // move file into the shared folder as recipient
481
+        Filesystem::rename('/folder2', '/folder1/folder2');
482 482
 
483
-		$this->assertFalse($this->rootView->file_exists($v1));
484
-		$this->assertFalse($this->rootView->file_exists($v2));
483
+        $this->assertFalse($this->rootView->file_exists($v1));
484
+        $this->assertFalse($this->rootView->file_exists($v2));
485 485
 
486
-		self::loginHelper(self::TEST_VERSIONS_USER);
486
+        self::loginHelper(self::TEST_VERSIONS_USER);
487 487
 
488
-		$versionsFolder1 = '/' . self::TEST_VERSIONS_USER . '/files_versions';
488
+        $versionsFolder1 = '/' . self::TEST_VERSIONS_USER . '/files_versions';
489 489
 
490
-		$v1Renamed = $versionsFolder1 . '/folder1/folder2/test.txt.v' . $t1;
491
-		$v2Renamed = $versionsFolder1 . '/folder1/folder2/test.txt.v' . $t2;
490
+        $v1Renamed = $versionsFolder1 . '/folder1/folder2/test.txt.v' . $t1;
491
+        $v2Renamed = $versionsFolder1 . '/folder1/folder2/test.txt.v' . $t2;
492 492
 
493
-		$this->assertTrue($this->rootView->file_exists($v1Renamed));
494
-		$this->assertTrue($this->rootView->file_exists($v2Renamed));
493
+        $this->assertTrue($this->rootView->file_exists($v1Renamed));
494
+        $this->assertTrue($this->rootView->file_exists($v2Renamed));
495 495
 
496
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
497
-	}
496
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
497
+    }
498 498
 
499
-	public function testRenameSharedFile(): void {
500
-		Filesystem::file_put_contents('test.txt', 'test file');
499
+    public function testRenameSharedFile(): void {
500
+        Filesystem::file_put_contents('test.txt', 'test file');
501 501
 
502
-		$t1 = time();
503
-		// second version is two weeks older, this way we make sure that no
504
-		// version will be expired
505
-		$t2 = $t1 - 60 * 60 * 24 * 14;
502
+        $t1 = time();
503
+        // second version is two weeks older, this way we make sure that no
504
+        // version will be expired
505
+        $t2 = $t1 - 60 * 60 * 24 * 14;
506 506
 
507
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT);
508
-		// create some versions
509
-		$v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
510
-		$v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
511
-		// the renamed versions should not exist! Because we only moved the mount point!
512
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
513
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
507
+        $this->rootView->mkdir(self::USERS_VERSIONS_ROOT);
508
+        // create some versions
509
+        $v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
510
+        $v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
511
+        // the renamed versions should not exist! Because we only moved the mount point!
512
+        $v1Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
513
+        $v2Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
514 514
 
515
-		$this->rootView->file_put_contents($v1, 'version1');
516
-		$this->rootView->file_put_contents($v2, 'version2');
515
+        $this->rootView->file_put_contents($v1, 'version1');
516
+        $this->rootView->file_put_contents($v2, 'version2');
517 517
 
518
-		$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('test.txt');
519
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
520
-		$share->setNode($node)
521
-			->setShareType(IShare::TYPE_USER)
522
-			->setSharedBy(self::TEST_VERSIONS_USER)
523
-			->setSharedWith(self::TEST_VERSIONS_USER2)
524
-			->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE | Constants::PERMISSION_SHARE);
525
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
526
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
518
+        $node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('test.txt');
519
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
520
+        $share->setNode($node)
521
+            ->setShareType(IShare::TYPE_USER)
522
+            ->setSharedBy(self::TEST_VERSIONS_USER)
523
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
524
+            ->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE | Constants::PERMISSION_SHARE);
525
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
526
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
527 527
 
528
-		self::loginHelper(self::TEST_VERSIONS_USER2);
528
+        self::loginHelper(self::TEST_VERSIONS_USER2);
529 529
 
530
-		$this->assertTrue(Filesystem::file_exists('test.txt'));
530
+        $this->assertTrue(Filesystem::file_exists('test.txt'));
531 531
 
532
-		// execute rename hook of versions app
533
-		Filesystem::rename('test.txt', 'test2.txt');
532
+        // execute rename hook of versions app
533
+        Filesystem::rename('test.txt', 'test2.txt');
534 534
 
535
-		self::loginHelper(self::TEST_VERSIONS_USER);
535
+        self::loginHelper(self::TEST_VERSIONS_USER);
536 536
 
537
-		$this->runCommands();
537
+        $this->runCommands();
538 538
 
539
-		$this->assertTrue($this->rootView->file_exists($v1));
540
-		$this->assertTrue($this->rootView->file_exists($v2));
539
+        $this->assertTrue($this->rootView->file_exists($v1));
540
+        $this->assertTrue($this->rootView->file_exists($v2));
541 541
 
542
-		$this->assertFalse($this->rootView->file_exists($v1Renamed));
543
-		$this->assertFalse($this->rootView->file_exists($v2Renamed));
542
+        $this->assertFalse($this->rootView->file_exists($v1Renamed));
543
+        $this->assertFalse($this->rootView->file_exists($v2Renamed));
544 544
 
545
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
546
-	}
545
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
546
+    }
547 547
 
548
-	public function testCopy(): void {
549
-		Filesystem::file_put_contents('test.txt', 'test file');
548
+    public function testCopy(): void {
549
+        Filesystem::file_put_contents('test.txt', 'test file');
550 550
 
551
-		$t1 = time();
552
-		// second version is two weeks older, this way we make sure that no
553
-		// version will be expired
554
-		$t2 = $t1 - 60 * 60 * 24 * 14;
551
+        $t1 = time();
552
+        // second version is two weeks older, this way we make sure that no
553
+        // version will be expired
554
+        $t2 = $t1 - 60 * 60 * 24 * 14;
555 555
 
556
-		// create some versions
557
-		$v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
558
-		$v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
559
-		$v1Copied = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
560
-		$v2Copied = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
556
+        // create some versions
557
+        $v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
558
+        $v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
559
+        $v1Copied = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
560
+        $v2Copied = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
561 561
 
562
-		$this->rootView->file_put_contents($v1, 'version1');
563
-		$this->rootView->file_put_contents($v2, 'version2');
562
+        $this->rootView->file_put_contents($v1, 'version1');
563
+        $this->rootView->file_put_contents($v2, 'version2');
564 564
 
565
-		// execute copy hook of versions app
566
-		Filesystem::copy('test.txt', 'test2.txt');
565
+        // execute copy hook of versions app
566
+        Filesystem::copy('test.txt', 'test2.txt');
567 567
 
568
-		$this->runCommands();
568
+        $this->runCommands();
569 569
 
570
-		$this->assertTrue($this->rootView->file_exists($v1), 'version 1 of original file exists');
571
-		$this->assertTrue($this->rootView->file_exists($v2), 'version 2 of original file exists');
570
+        $this->assertTrue($this->rootView->file_exists($v1), 'version 1 of original file exists');
571
+        $this->assertTrue($this->rootView->file_exists($v2), 'version 2 of original file exists');
572 572
 
573
-		$this->assertTrue($this->rootView->file_exists($v1Copied), 'version 1 of copied file exists');
574
-		$this->assertTrue($this->rootView->file_exists($v2Copied), 'version 2 of copied file exists');
575
-	}
573
+        $this->assertTrue($this->rootView->file_exists($v1Copied), 'version 1 of copied file exists');
574
+        $this->assertTrue($this->rootView->file_exists($v2Copied), 'version 2 of copied file exists');
575
+    }
576 576
 
577
-	/**
578
-	 * test if we find all versions and if the versions array contain
579
-	 * the correct 'path' and 'name'
580
-	 */
581
-	public function testGetVersions(): void {
582
-		$t1 = time();
583
-		// second version is two weeks older, this way we make sure that no
584
-		// version will be expired
585
-		$t2 = $t1 - 60 * 60 * 24 * 14;
577
+    /**
578
+     * test if we find all versions and if the versions array contain
579
+     * the correct 'path' and 'name'
580
+     */
581
+    public function testGetVersions(): void {
582
+        $t1 = time();
583
+        // second version is two weeks older, this way we make sure that no
584
+        // version will be expired
585
+        $t2 = $t1 - 60 * 60 * 24 * 14;
586 586
 
587
-		// create some versions
588
-		$v1 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t1;
589
-		$v2 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t2;
587
+        // create some versions
588
+        $v1 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t1;
589
+        $v2 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t2;
590 590
 
591
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/subfolder/');
591
+        $this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/subfolder/');
592 592
 
593
-		$this->rootView->file_put_contents($v1, 'version1');
594
-		$this->rootView->file_put_contents($v2, 'version2');
593
+        $this->rootView->file_put_contents($v1, 'version1');
594
+        $this->rootView->file_put_contents($v2, 'version2');
595 595
 
596
-		// execute copy hook of versions app
597
-		$versions = Storage::getVersions(self::TEST_VERSIONS_USER, '/subfolder/test.txt');
596
+        // execute copy hook of versions app
597
+        $versions = Storage::getVersions(self::TEST_VERSIONS_USER, '/subfolder/test.txt');
598 598
 
599
-		$this->assertCount(2, $versions);
599
+        $this->assertCount(2, $versions);
600 600
 
601
-		foreach ($versions as $version) {
602
-			$this->assertSame('/subfolder/test.txt', $version['path']);
603
-			$this->assertSame('test.txt', $version['name']);
604
-		}
601
+        foreach ($versions as $version) {
602
+            $this->assertSame('/subfolder/test.txt', $version['path']);
603
+            $this->assertSame('test.txt', $version['name']);
604
+        }
605 605
 
606
-		//cleanup
607
-		$this->rootView->deleteAll(self::USERS_VERSIONS_ROOT . '/subfolder');
608
-	}
606
+        //cleanup
607
+        $this->rootView->deleteAll(self::USERS_VERSIONS_ROOT . '/subfolder');
608
+    }
609 609
 
610
-	/**
611
-	 * test if we find all versions and if the versions array contain
612
-	 * the correct 'path' and 'name'
613
-	 */
614
-	public function testGetVersionsEmptyFile(): void {
615
-		// execute copy hook of versions app
616
-		$versions = Storage::getVersions(self::TEST_VERSIONS_USER, '');
617
-		$this->assertCount(0, $versions);
610
+    /**
611
+     * test if we find all versions and if the versions array contain
612
+     * the correct 'path' and 'name'
613
+     */
614
+    public function testGetVersionsEmptyFile(): void {
615
+        // execute copy hook of versions app
616
+        $versions = Storage::getVersions(self::TEST_VERSIONS_USER, '');
617
+        $this->assertCount(0, $versions);
618 618
 
619
-		$versions = Storage::getVersions(self::TEST_VERSIONS_USER, null);
620
-		$this->assertCount(0, $versions);
621
-	}
619
+        $versions = Storage::getVersions(self::TEST_VERSIONS_USER, null);
620
+        $this->assertCount(0, $versions);
621
+    }
622 622
 
623
-	public function testExpireNonexistingFile(): void {
624
-		$this->logout();
625
-		// needed to have a FS setup (the background job does this)
626
-		\OC_Util::setupFS(self::TEST_VERSIONS_USER);
623
+    public function testExpireNonexistingFile(): void {
624
+        $this->logout();
625
+        // needed to have a FS setup (the background job does this)
626
+        \OC_Util::setupFS(self::TEST_VERSIONS_USER);
627 627
 
628
-		$this->assertFalse(Storage::expire('/void/unexist.txt', self::TEST_VERSIONS_USER));
629
-	}
628
+        $this->assertFalse(Storage::expire('/void/unexist.txt', self::TEST_VERSIONS_USER));
629
+    }
630 630
 
631 631
 
632
-	public function testExpireNonexistingUser(): void {
633
-		$this->expectException(NoUserException::class);
632
+    public function testExpireNonexistingUser(): void {
633
+        $this->expectException(NoUserException::class);
634 634
 
635
-		$this->logout();
636
-		// needed to have a FS setup (the background job does this)
637
-		\OC_Util::setupFS(self::TEST_VERSIONS_USER);
638
-		Filesystem::file_put_contents('test.txt', 'test file');
635
+        $this->logout();
636
+        // needed to have a FS setup (the background job does this)
637
+        \OC_Util::setupFS(self::TEST_VERSIONS_USER);
638
+        Filesystem::file_put_contents('test.txt', 'test file');
639 639
 
640
-		$this->assertFalse(Storage::expire('test.txt', 'unexist'));
641
-	}
640
+        $this->assertFalse(Storage::expire('test.txt', 'unexist'));
641
+    }
642 642
 
643
-	public function testRestoreSameStorage(): void {
644
-		Filesystem::mkdir('sub');
645
-		$this->doTestRestore();
646
-	}
643
+    public function testRestoreSameStorage(): void {
644
+        Filesystem::mkdir('sub');
645
+        $this->doTestRestore();
646
+    }
647 647
 
648
-	public function testRestoreCrossStorage(): void {
649
-		$storage2 = new Temporary([]);
650
-		Filesystem::mount($storage2, [], self::TEST_VERSIONS_USER . '/files/sub');
648
+    public function testRestoreCrossStorage(): void {
649
+        $storage2 = new Temporary([]);
650
+        Filesystem::mount($storage2, [], self::TEST_VERSIONS_USER . '/files/sub');
651 651
 
652
-		$this->doTestRestore();
653
-	}
652
+        $this->doTestRestore();
653
+    }
654 654
 
655
-	public function testRestoreNoPermission(): void {
656
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
655
+    public function testRestoreNoPermission(): void {
656
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
657 657
 
658
-		$userHome = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER);
659
-		$node = $userHome->newFolder('folder');
660
-		$file = $node->newFile('test.txt');
658
+        $userHome = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER);
659
+        $node = $userHome->newFolder('folder');
660
+        $file = $node->newFile('test.txt');
661 661
 
662
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
663
-		$share->setNode($node)
664
-			->setShareType(IShare::TYPE_USER)
665
-			->setSharedBy(self::TEST_VERSIONS_USER)
666
-			->setSharedWith(self::TEST_VERSIONS_USER2)
667
-			->setPermissions(Constants::PERMISSION_READ);
668
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
669
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
670
-
671
-		$versions = $this->createAndCheckVersions(
672
-			Filesystem::getView(),
673
-			'folder/test.txt'
674
-		);
675
-
676
-		$file->putContent('test file');
677
-
678
-		$this->loginAsUser(self::TEST_VERSIONS_USER2);
662
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
663
+        $share->setNode($node)
664
+            ->setShareType(IShare::TYPE_USER)
665
+            ->setSharedBy(self::TEST_VERSIONS_USER)
666
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
667
+            ->setPermissions(Constants::PERMISSION_READ);
668
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
669
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
670
+
671
+        $versions = $this->createAndCheckVersions(
672
+            Filesystem::getView(),
673
+            'folder/test.txt'
674
+        );
675
+
676
+        $file->putContent('test file');
677
+
678
+        $this->loginAsUser(self::TEST_VERSIONS_USER2);
679 679
 
680
-		$firstVersion = current($versions);
680
+        $firstVersion = current($versions);
681 681
 
682
-		$this->assertFalse(Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user2), 'Revert did not happen');
682
+        $this->assertFalse(Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user2), 'Revert did not happen');
683 683
 
684
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
684
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
685 685
 
686
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
687
-		$this->assertEquals('test file', $file->getContent(), 'File content has not changed');
688
-	}
686
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
687
+        $this->assertEquals('test file', $file->getContent(), 'File content has not changed');
688
+    }
689 689
 
690
-	public function testRestoreMovedShare(): void {
691
-		$this->markTestSkipped('Unreliable test');
692
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
693
-
694
-		$userHome = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER);
695
-		$node = $userHome->newFolder('folder');
696
-		$file = $node->newFile('test.txt');
697
-
698
-		$userHome2 = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER2);
699
-		$userHome2->newFolder('subfolder');
700
-
701
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
702
-		$share->setNode($node)
703
-			->setShareType(IShare::TYPE_USER)
704
-			->setSharedBy(self::TEST_VERSIONS_USER)
705
-			->setSharedWith(self::TEST_VERSIONS_USER2)
706
-			->setPermissions(Constants::PERMISSION_ALL);
707
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
708
-		$shareManager = Server::get(\OCP\Share\IManager::class);
709
-		$shareManager->acceptShare($share, self::TEST_VERSIONS_USER2);
710
-
711
-		$share->setTarget('subfolder/folder');
712
-		$shareManager->moveShare($share, self::TEST_VERSIONS_USER2);
713
-
714
-		$versions = $this->createAndCheckVersions(
715
-			Filesystem::getView(),
716
-			'folder/test.txt'
717
-		);
718
-
719
-		$file->putContent('test file');
720
-
721
-		$this->loginAsUser(self::TEST_VERSIONS_USER2);
722
-
723
-		$firstVersion = current($versions);
724
-
725
-		$this->assertTrue(Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user1));
726
-
727
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
728
-
729
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
730
-		$this->assertEquals('version 2', $file->getContent(), 'File content has not changed');
731
-	}
732
-
733
-	/**
734
-	 * @param string $hookName name of hook called
735
-	 * @param string $params variable to receive parameters provided by hook
736
-	 */
737
-	private function connectMockHooks($hookName, &$params) {
738
-		if ($hookName === null) {
739
-			return;
740
-		}
741
-
742
-		$eventHandler = $this->getMockBuilder(\stdclass::class)
743
-			->setMethods(['callback'])
744
-			->getMock();
745
-
746
-		$eventHandler->expects($this->any())
747
-			->method('callback')
748
-			->willReturnCallback(
749
-				function ($p) use (&$params): void {
750
-					$params = $p;
751
-				}
752
-			);
753
-
754
-		Util::connectHook(
755
-			'\OCP\Versions',
756
-			$hookName,
757
-			$eventHandler,
758
-			'callback'
759
-		);
760
-	}
761
-
762
-	private function doTestRestore() {
763
-		$filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt';
764
-		$this->rootView->file_put_contents($filePath, 'test file');
765
-
766
-		$fileInfo = $this->rootView->getFileInfo($filePath);
767
-		$t0 = $this->rootView->filemtime($filePath);
768
-
769
-		// not exactly the same timestamp as the file
770
-		$t1 = time() - 60;
771
-		// second version is two weeks older
772
-		$t2 = $t1 - 60 * 60 * 24 * 14;
773
-
774
-		// create some versions
775
-		$v1 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t1;
776
-		$v2 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t2;
777
-
778
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/sub');
779
-
780
-		$this->rootView->file_put_contents($v1, 'version1');
781
-		$fileInfoV1 = $this->rootView->getFileInfo($v1);
782
-		$versionEntity = new VersionEntity();
783
-		$versionEntity->setFileId($fileInfo->getId());
784
-		$versionEntity->setTimestamp($t1);
785
-		$versionEntity->setSize($fileInfoV1->getSize());
786
-		$versionEntity->setMimetype($this->mimeTypeLoader->getId($fileInfoV1->getMimetype()));
787
-		$versionEntity->setMetadata([]);
788
-		$this->versionsMapper->insert($versionEntity);
789
-
790
-		$this->rootView->file_put_contents($v2, 'version2');
791
-		$fileInfoV2 = $this->rootView->getFileInfo($v2);
792
-		$versionEntity = new VersionEntity();
793
-		$versionEntity->setFileId($fileInfo->getId());
794
-		$versionEntity->setTimestamp($t2);
795
-		$versionEntity->setSize($fileInfoV2->getSize());
796
-		$versionEntity->setMimetype($this->mimeTypeLoader->getId($fileInfoV2->getMimetype()));
797
-		$versionEntity->setMetadata([]);
798
-		$this->versionsMapper->insert($versionEntity);
799
-
800
-		$oldVersions = Storage::getVersions(
801
-			self::TEST_VERSIONS_USER, '/sub/test.txt'
802
-		);
803
-
804
-		$this->assertCount(2, $oldVersions);
805
-
806
-		$this->assertEquals('test file', $this->rootView->file_get_contents($filePath));
807
-		$info1 = $this->rootView->getFileInfo($filePath);
808
-
809
-		$eventDispatcher = Server::get(IEventDispatcher::class);
810
-		$eventFired = false;
811
-		$eventDispatcher->addListener(VersionRestoredEvent::class, function ($event) use (&$eventFired, $t2): void {
812
-			$eventFired = true;
813
-			$this->assertEquals('/sub/test.txt', $event->getVersion()->getVersionPath());
814
-			$this->assertTrue($event->getVersion()->getRevisionId() > 0);
815
-		});
816
-
817
-		$versionManager = Server::get(IVersionManager::class);
818
-		$versions = $versionManager->getVersionsForFile($this->user1, $info1);
819
-		$version = array_filter($versions, function ($version) use ($t2) {
820
-			return $version->getRevisionId() === $t2;
821
-		});
822
-		$this->assertTrue($versionManager->rollback(current($version)));
823
-
824
-		$this->assertTrue($eventFired, 'VersionRestoredEvent was not fired');
825
-
826
-		$this->assertEquals('version2', $this->rootView->file_get_contents($filePath));
827
-		$info2 = $this->rootView->getFileInfo($filePath);
828
-
829
-		$this->assertNotEquals(
830
-			$info2['etag'],
831
-			$info1['etag'],
832
-			'Etag must change after rolling back version'
833
-		);
834
-		$this->assertEquals(
835
-			$info2['fileid'],
836
-			$info1['fileid'],
837
-			'File id must not change after rolling back version'
838
-		);
839
-		$this->assertEquals(
840
-			$info2['mtime'],
841
-			$t2,
842
-			'Restored file has mtime from version'
843
-		);
844
-
845
-		$newVersions = Storage::getVersions(
846
-			self::TEST_VERSIONS_USER, '/sub/test.txt'
847
-		);
848
-
849
-		$this->assertTrue(
850
-			$this->rootView->file_exists(self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t0),
851
-			'A version file was created for the file before restoration'
852
-		);
853
-		$this->assertTrue(
854
-			$this->rootView->file_exists($v1),
855
-			'Untouched version file is still there'
856
-		);
857
-		$this->assertFalse(
858
-			$this->rootView->file_exists($v2),
859
-			'Restored version file gone from files_version folder'
860
-		);
861
-
862
-		$this->assertCount(2, $newVersions, 'Additional version created');
863
-
864
-		$this->assertTrue(
865
-			isset($newVersions[$t0 . '#' . 'test.txt']),
866
-			'A version was created for the file before restoration'
867
-		);
868
-		$this->assertTrue(
869
-			isset($newVersions[$t1 . '#' . 'test.txt']),
870
-			'Untouched version is still there'
871
-		);
872
-		$this->assertFalse(
873
-			isset($newVersions[$t2 . '#' . 'test.txt']),
874
-			'Restored version is not in the list any more'
875
-		);
876
-	}
877
-
878
-	/**
879
-	 * Test whether versions are created when overwriting as owner
880
-	 */
881
-	public function testStoreVersionAsOwner(): void {
882
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
883
-
884
-		$this->createAndCheckVersions(
885
-			Filesystem::getView(),
886
-			'test.txt'
887
-		);
888
-	}
889
-
890
-	/**
891
-	 * Test whether versions are created when overwriting as share recipient
892
-	 */
893
-	public function testStoreVersionAsRecipient(): void {
894
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
895
-
896
-		Filesystem::mkdir('folder');
897
-		Filesystem::file_put_contents('folder/test.txt', 'test file');
898
-
899
-		$node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder');
900
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
901
-		$share->setNode($node)
902
-			->setShareType(IShare::TYPE_USER)
903
-			->setSharedBy(self::TEST_VERSIONS_USER)
904
-			->setSharedWith(self::TEST_VERSIONS_USER2)
905
-			->setPermissions(Constants::PERMISSION_ALL);
906
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
907
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
908
-
909
-		$this->loginAsUser(self::TEST_VERSIONS_USER2);
910
-
911
-		$this->createAndCheckVersions(
912
-			Filesystem::getView(),
913
-			'folder/test.txt'
914
-		);
915
-
916
-		Server::get(\OCP\Share\IManager::class)->deleteShare($share);
917
-	}
918
-
919
-	/**
920
-	 * Test whether versions are created when overwriting anonymously.
921
-	 *
922
-	 * When uploading through a public link or publicwebdav, no user
923
-	 * is logged in. File modification must still be able to find
924
-	 * the owner and create versions.
925
-	 */
926
-	public function testStoreVersionAsAnonymous(): void {
927
-		$this->logout();
928
-
929
-		// note: public link upload does this,
930
-		// needed to make the hooks fire
931
-		\OC_Util::setupFS(self::TEST_VERSIONS_USER);
932
-
933
-		$userView = new View('/' . self::TEST_VERSIONS_USER . '/files');
934
-		$this->createAndCheckVersions(
935
-			$userView,
936
-			'test.txt'
937
-		);
938
-	}
939
-
940
-	/**
941
-	 * @param View $view
942
-	 * @param string $path
943
-	 */
944
-	private function createAndCheckVersions(View $view, $path) {
945
-		$view->file_put_contents($path, 'test file');
946
-		$view->file_put_contents($path, 'version 1');
947
-		$view->file_put_contents($path, 'version 2');
948
-
949
-		$this->loginAsUser(self::TEST_VERSIONS_USER);
950
-
951
-		// need to scan for the versions
952
-		[$rootStorage,] = $this->rootView->resolvePath(self::TEST_VERSIONS_USER . '/files_versions');
953
-		$rootStorage->getScanner()->scan('files_versions');
954
-
955
-		$versions = Storage::getVersions(
956
-			self::TEST_VERSIONS_USER, '/' . $path
957
-		);
958
-
959
-		// note: we cannot predict how many versions are created due to
960
-		// test run timing
961
-		$this->assertGreaterThan(0, count($versions));
962
-
963
-		return $versions;
964
-	}
965
-
966
-	/**
967
-	 * @param string $user
968
-	 * @param bool $create
969
-	 */
970
-	public static function loginHelper($user, $create = false) {
971
-		if ($create) {
972
-			$backend = new \Test\Util\User\Dummy();
973
-			$backend->createUser($user, $user);
974
-			Server::get(IUserManager::class)->registerBackend($backend);
975
-		}
976
-
977
-		\OC_Util::tearDownFS();
978
-		\OC_User::setUserId('');
979
-		Filesystem::tearDown();
980
-		\OC_User::setUserId($user);
981
-		\OC_Util::setupFS($user);
982
-		\OC::$server->getUserFolder($user);
983
-	}
690
+    public function testRestoreMovedShare(): void {
691
+        $this->markTestSkipped('Unreliable test');
692
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
693
+
694
+        $userHome = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER);
695
+        $node = $userHome->newFolder('folder');
696
+        $file = $node->newFile('test.txt');
697
+
698
+        $userHome2 = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER2);
699
+        $userHome2->newFolder('subfolder');
700
+
701
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
702
+        $share->setNode($node)
703
+            ->setShareType(IShare::TYPE_USER)
704
+            ->setSharedBy(self::TEST_VERSIONS_USER)
705
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
706
+            ->setPermissions(Constants::PERMISSION_ALL);
707
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
708
+        $shareManager = Server::get(\OCP\Share\IManager::class);
709
+        $shareManager->acceptShare($share, self::TEST_VERSIONS_USER2);
710
+
711
+        $share->setTarget('subfolder/folder');
712
+        $shareManager->moveShare($share, self::TEST_VERSIONS_USER2);
713
+
714
+        $versions = $this->createAndCheckVersions(
715
+            Filesystem::getView(),
716
+            'folder/test.txt'
717
+        );
718
+
719
+        $file->putContent('test file');
720
+
721
+        $this->loginAsUser(self::TEST_VERSIONS_USER2);
722
+
723
+        $firstVersion = current($versions);
724
+
725
+        $this->assertTrue(Storage::rollback('folder/test.txt', $firstVersion['version'], $this->user1));
726
+
727
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
728
+
729
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
730
+        $this->assertEquals('version 2', $file->getContent(), 'File content has not changed');
731
+    }
732
+
733
+    /**
734
+     * @param string $hookName name of hook called
735
+     * @param string $params variable to receive parameters provided by hook
736
+     */
737
+    private function connectMockHooks($hookName, &$params) {
738
+        if ($hookName === null) {
739
+            return;
740
+        }
741
+
742
+        $eventHandler = $this->getMockBuilder(\stdclass::class)
743
+            ->setMethods(['callback'])
744
+            ->getMock();
745
+
746
+        $eventHandler->expects($this->any())
747
+            ->method('callback')
748
+            ->willReturnCallback(
749
+                function ($p) use (&$params): void {
750
+                    $params = $p;
751
+                }
752
+            );
753
+
754
+        Util::connectHook(
755
+            '\OCP\Versions',
756
+            $hookName,
757
+            $eventHandler,
758
+            'callback'
759
+        );
760
+    }
761
+
762
+    private function doTestRestore() {
763
+        $filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt';
764
+        $this->rootView->file_put_contents($filePath, 'test file');
765
+
766
+        $fileInfo = $this->rootView->getFileInfo($filePath);
767
+        $t0 = $this->rootView->filemtime($filePath);
768
+
769
+        // not exactly the same timestamp as the file
770
+        $t1 = time() - 60;
771
+        // second version is two weeks older
772
+        $t2 = $t1 - 60 * 60 * 24 * 14;
773
+
774
+        // create some versions
775
+        $v1 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t1;
776
+        $v2 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t2;
777
+
778
+        $this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/sub');
779
+
780
+        $this->rootView->file_put_contents($v1, 'version1');
781
+        $fileInfoV1 = $this->rootView->getFileInfo($v1);
782
+        $versionEntity = new VersionEntity();
783
+        $versionEntity->setFileId($fileInfo->getId());
784
+        $versionEntity->setTimestamp($t1);
785
+        $versionEntity->setSize($fileInfoV1->getSize());
786
+        $versionEntity->setMimetype($this->mimeTypeLoader->getId($fileInfoV1->getMimetype()));
787
+        $versionEntity->setMetadata([]);
788
+        $this->versionsMapper->insert($versionEntity);
789
+
790
+        $this->rootView->file_put_contents($v2, 'version2');
791
+        $fileInfoV2 = $this->rootView->getFileInfo($v2);
792
+        $versionEntity = new VersionEntity();
793
+        $versionEntity->setFileId($fileInfo->getId());
794
+        $versionEntity->setTimestamp($t2);
795
+        $versionEntity->setSize($fileInfoV2->getSize());
796
+        $versionEntity->setMimetype($this->mimeTypeLoader->getId($fileInfoV2->getMimetype()));
797
+        $versionEntity->setMetadata([]);
798
+        $this->versionsMapper->insert($versionEntity);
799
+
800
+        $oldVersions = Storage::getVersions(
801
+            self::TEST_VERSIONS_USER, '/sub/test.txt'
802
+        );
803
+
804
+        $this->assertCount(2, $oldVersions);
805
+
806
+        $this->assertEquals('test file', $this->rootView->file_get_contents($filePath));
807
+        $info1 = $this->rootView->getFileInfo($filePath);
808
+
809
+        $eventDispatcher = Server::get(IEventDispatcher::class);
810
+        $eventFired = false;
811
+        $eventDispatcher->addListener(VersionRestoredEvent::class, function ($event) use (&$eventFired, $t2): void {
812
+            $eventFired = true;
813
+            $this->assertEquals('/sub/test.txt', $event->getVersion()->getVersionPath());
814
+            $this->assertTrue($event->getVersion()->getRevisionId() > 0);
815
+        });
816
+
817
+        $versionManager = Server::get(IVersionManager::class);
818
+        $versions = $versionManager->getVersionsForFile($this->user1, $info1);
819
+        $version = array_filter($versions, function ($version) use ($t2) {
820
+            return $version->getRevisionId() === $t2;
821
+        });
822
+        $this->assertTrue($versionManager->rollback(current($version)));
823
+
824
+        $this->assertTrue($eventFired, 'VersionRestoredEvent was not fired');
825
+
826
+        $this->assertEquals('version2', $this->rootView->file_get_contents($filePath));
827
+        $info2 = $this->rootView->getFileInfo($filePath);
828
+
829
+        $this->assertNotEquals(
830
+            $info2['etag'],
831
+            $info1['etag'],
832
+            'Etag must change after rolling back version'
833
+        );
834
+        $this->assertEquals(
835
+            $info2['fileid'],
836
+            $info1['fileid'],
837
+            'File id must not change after rolling back version'
838
+        );
839
+        $this->assertEquals(
840
+            $info2['mtime'],
841
+            $t2,
842
+            'Restored file has mtime from version'
843
+        );
844
+
845
+        $newVersions = Storage::getVersions(
846
+            self::TEST_VERSIONS_USER, '/sub/test.txt'
847
+        );
848
+
849
+        $this->assertTrue(
850
+            $this->rootView->file_exists(self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t0),
851
+            'A version file was created for the file before restoration'
852
+        );
853
+        $this->assertTrue(
854
+            $this->rootView->file_exists($v1),
855
+            'Untouched version file is still there'
856
+        );
857
+        $this->assertFalse(
858
+            $this->rootView->file_exists($v2),
859
+            'Restored version file gone from files_version folder'
860
+        );
861
+
862
+        $this->assertCount(2, $newVersions, 'Additional version created');
863
+
864
+        $this->assertTrue(
865
+            isset($newVersions[$t0 . '#' . 'test.txt']),
866
+            'A version was created for the file before restoration'
867
+        );
868
+        $this->assertTrue(
869
+            isset($newVersions[$t1 . '#' . 'test.txt']),
870
+            'Untouched version is still there'
871
+        );
872
+        $this->assertFalse(
873
+            isset($newVersions[$t2 . '#' . 'test.txt']),
874
+            'Restored version is not in the list any more'
875
+        );
876
+    }
877
+
878
+    /**
879
+     * Test whether versions are created when overwriting as owner
880
+     */
881
+    public function testStoreVersionAsOwner(): void {
882
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
883
+
884
+        $this->createAndCheckVersions(
885
+            Filesystem::getView(),
886
+            'test.txt'
887
+        );
888
+    }
889
+
890
+    /**
891
+     * Test whether versions are created when overwriting as share recipient
892
+     */
893
+    public function testStoreVersionAsRecipient(): void {
894
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
895
+
896
+        Filesystem::mkdir('folder');
897
+        Filesystem::file_put_contents('folder/test.txt', 'test file');
898
+
899
+        $node = \OC::$server->getUserFolder(self::TEST_VERSIONS_USER)->get('folder');
900
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
901
+        $share->setNode($node)
902
+            ->setShareType(IShare::TYPE_USER)
903
+            ->setSharedBy(self::TEST_VERSIONS_USER)
904
+            ->setSharedWith(self::TEST_VERSIONS_USER2)
905
+            ->setPermissions(Constants::PERMISSION_ALL);
906
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
907
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
908
+
909
+        $this->loginAsUser(self::TEST_VERSIONS_USER2);
910
+
911
+        $this->createAndCheckVersions(
912
+            Filesystem::getView(),
913
+            'folder/test.txt'
914
+        );
915
+
916
+        Server::get(\OCP\Share\IManager::class)->deleteShare($share);
917
+    }
918
+
919
+    /**
920
+     * Test whether versions are created when overwriting anonymously.
921
+     *
922
+     * When uploading through a public link or publicwebdav, no user
923
+     * is logged in. File modification must still be able to find
924
+     * the owner and create versions.
925
+     */
926
+    public function testStoreVersionAsAnonymous(): void {
927
+        $this->logout();
928
+
929
+        // note: public link upload does this,
930
+        // needed to make the hooks fire
931
+        \OC_Util::setupFS(self::TEST_VERSIONS_USER);
932
+
933
+        $userView = new View('/' . self::TEST_VERSIONS_USER . '/files');
934
+        $this->createAndCheckVersions(
935
+            $userView,
936
+            'test.txt'
937
+        );
938
+    }
939
+
940
+    /**
941
+     * @param View $view
942
+     * @param string $path
943
+     */
944
+    private function createAndCheckVersions(View $view, $path) {
945
+        $view->file_put_contents($path, 'test file');
946
+        $view->file_put_contents($path, 'version 1');
947
+        $view->file_put_contents($path, 'version 2');
948
+
949
+        $this->loginAsUser(self::TEST_VERSIONS_USER);
950
+
951
+        // need to scan for the versions
952
+        [$rootStorage,] = $this->rootView->resolvePath(self::TEST_VERSIONS_USER . '/files_versions');
953
+        $rootStorage->getScanner()->scan('files_versions');
954
+
955
+        $versions = Storage::getVersions(
956
+            self::TEST_VERSIONS_USER, '/' . $path
957
+        );
958
+
959
+        // note: we cannot predict how many versions are created due to
960
+        // test run timing
961
+        $this->assertGreaterThan(0, count($versions));
962
+
963
+        return $versions;
964
+    }
965
+
966
+    /**
967
+     * @param string $user
968
+     * @param bool $create
969
+     */
970
+    public static function loginHelper($user, $create = false) {
971
+        if ($create) {
972
+            $backend = new \Test\Util\User\Dummy();
973
+            $backend->createUser($user, $user);
974
+            Server::get(IUserManager::class)->registerBackend($backend);
975
+        }
976
+
977
+        \OC_Util::tearDownFS();
978
+        \OC_User::setUserId('');
979
+        Filesystem::tearDown();
980
+        \OC_User::setUserId($user);
981
+        \OC_Util::setupFS($user);
982
+        \OC::$server->getUserFolder($user);
983
+    }
984 984
 }
985 985
 
986 986
 // extend the original class to make it possible to test protected methods
987 987
 class VersionStorageToTest extends Storage {
988 988
 
989
-	/**
990
-	 * @param integer $time
991
-	 */
992
-	public function callProtectedGetExpireList($time, $versions) {
993
-		return self::getExpireList($time, $versions);
994
-	}
989
+    /**
990
+     * @param integer $time
991
+     */
992
+    public function callProtectedGetExpireList($time, $versions) {
993
+        return self::getExpireList($time, $versions);
994
+    }
995 995
 }
Please login to merge, or discard this patch.
Spacing   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -86,7 +86,7 @@  discard block
 block discarded – undo
86 86
 		$mockConfig = $this->createMock(IConfig::class);
87 87
 		$mockConfig->expects($this->any())
88 88
 			->method('getSystemValue')
89
-			->willReturnCallback(function ($key, $default) use ($config) {
89
+			->willReturnCallback(function($key, $default) use ($config) {
90 90
 				if ($key === 'filesystem_check_changes') {
91 91
 					return Watcher::CHECK_ONCE;
92 92
 				} else {
@@ -121,10 +121,10 @@  discard block
 block discarded – undo
121 121
 		$this->restoreService(AllConfig::class);
122 122
 
123 123
 		if ($this->rootView) {
124
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files/');
125
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files/');
126
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files_versions/');
127
-			$this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files_versions/');
124
+			$this->rootView->deleteAll(self::TEST_VERSIONS_USER.'/files/');
125
+			$this->rootView->deleteAll(self::TEST_VERSIONS_USER2.'/files/');
126
+			$this->rootView->deleteAll(self::TEST_VERSIONS_USER.'/files_versions/');
127
+			$this->rootView->deleteAll(self::TEST_VERSIONS_USER2.'/files_versions/');
128 128
 		}
129 129
 
130 130
 		\OC_Hook::clear();
@@ -292,10 +292,10 @@  discard block
 block discarded – undo
292 292
 		$t2 = $t1 - 60 * 60 * 24 * 14;
293 293
 
294 294
 		// create some versions
295
-		$v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
296
-		$v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
297
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
298
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
295
+		$v1 = self::USERS_VERSIONS_ROOT.'/test.txt.v'.$t1;
296
+		$v2 = self::USERS_VERSIONS_ROOT.'/test.txt.v'.$t2;
297
+		$v1Renamed = self::USERS_VERSIONS_ROOT.'/test2.txt.v'.$t1;
298
+		$v2Renamed = self::USERS_VERSIONS_ROOT.'/test2.txt.v'.$t2;
299 299
 
300 300
 		$this->rootView->file_put_contents($v1, 'version1');
301 301
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -322,12 +322,12 @@  discard block
 block discarded – undo
322 322
 		// version will be expired
323 323
 		$t2 = $t1 - 60 * 60 * 24 * 14;
324 324
 
325
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/folder1');
325
+		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT.'/folder1');
326 326
 		// create some versions
327
-		$v1 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t1;
328
-		$v2 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t2;
329
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/folder1/folder2/test.txt.v' . $t1;
330
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/folder1/folder2/test.txt.v' . $t2;
327
+		$v1 = self::USERS_VERSIONS_ROOT.'/folder1/test.txt.v'.$t1;
328
+		$v2 = self::USERS_VERSIONS_ROOT.'/folder1/test.txt.v'.$t2;
329
+		$v1Renamed = self::USERS_VERSIONS_ROOT.'/folder1/folder2/test.txt.v'.$t1;
330
+		$v2Renamed = self::USERS_VERSIONS_ROOT.'/folder1/folder2/test.txt.v'.$t2;
331 331
 
332 332
 		$this->rootView->file_put_contents($v1, 'version1');
333 333
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -373,11 +373,11 @@  discard block
 block discarded – undo
373 373
 		$t2 = $t1 - 60 * 60 * 24 * 14;
374 374
 
375 375
 		// create some versions
376
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/folder1');
377
-		$v1 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t1;
378
-		$v2 = self::USERS_VERSIONS_ROOT . '/folder1/test.txt.v' . $t2;
379
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/folder2/folder1/test.txt.v' . $t1;
380
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/folder2/folder1/test.txt.v' . $t2;
376
+		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT.'/folder1');
377
+		$v1 = self::USERS_VERSIONS_ROOT.'/folder1/test.txt.v'.$t1;
378
+		$v2 = self::USERS_VERSIONS_ROOT.'/folder1/test.txt.v'.$t2;
379
+		$v1Renamed = self::USERS_VERSIONS_ROOT.'/folder2/folder1/test.txt.v'.$t1;
380
+		$v2Renamed = self::USERS_VERSIONS_ROOT.'/folder2/folder1/test.txt.v'.$t2;
381 381
 
382 382
 		$this->rootView->file_put_contents($v1, 'version1');
383 383
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -410,7 +410,7 @@  discard block
 block discarded – undo
410 410
 		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
411 411
 
412 412
 		self::loginHelper(self::TEST_VERSIONS_USER2);
413
-		$versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
413
+		$versionsFolder2 = '/'.self::TEST_VERSIONS_USER2.'/files_versions';
414 414
 		Filesystem::file_put_contents('test.txt', 'test file');
415 415
 
416 416
 		$t1 = time();
@@ -420,8 +420,8 @@  discard block
 block discarded – undo
420 420
 
421 421
 		$this->rootView->mkdir($versionsFolder2);
422 422
 		// create some versions
423
-		$v1 = $versionsFolder2 . '/test.txt.v' . $t1;
424
-		$v2 = $versionsFolder2 . '/test.txt.v' . $t2;
423
+		$v1 = $versionsFolder2.'/test.txt.v'.$t1;
424
+		$v2 = $versionsFolder2.'/test.txt.v'.$t2;
425 425
 
426 426
 		$this->rootView->file_put_contents($v1, 'version1');
427 427
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -434,10 +434,10 @@  discard block
 block discarded – undo
434 434
 
435 435
 		self::loginHelper(self::TEST_VERSIONS_USER);
436 436
 
437
-		$versionsFolder1 = '/' . self::TEST_VERSIONS_USER . '/files_versions';
437
+		$versionsFolder1 = '/'.self::TEST_VERSIONS_USER.'/files_versions';
438 438
 
439
-		$v1Renamed = $versionsFolder1 . '/folder1/test.txt.v' . $t1;
440
-		$v2Renamed = $versionsFolder1 . '/folder1/test.txt.v' . $t2;
439
+		$v1Renamed = $versionsFolder1.'/folder1/test.txt.v'.$t1;
440
+		$v2Renamed = $versionsFolder1.'/folder1/test.txt.v'.$t2;
441 441
 
442 442
 		$this->assertTrue($this->rootView->file_exists($v1Renamed));
443 443
 		$this->assertTrue($this->rootView->file_exists($v2Renamed));
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
 		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_VERSIONS_USER2);
460 460
 
461 461
 		self::loginHelper(self::TEST_VERSIONS_USER2);
462
-		$versionsFolder2 = '/' . self::TEST_VERSIONS_USER2 . '/files_versions';
462
+		$versionsFolder2 = '/'.self::TEST_VERSIONS_USER2.'/files_versions';
463 463
 		Filesystem::mkdir('folder2');
464 464
 		Filesystem::file_put_contents('folder2/test.txt', 'test file');
465 465
 
@@ -469,10 +469,10 @@  discard block
 block discarded – undo
469 469
 		$t2 = $t1 - 60 * 60 * 24 * 14;
470 470
 
471 471
 		$this->rootView->mkdir($versionsFolder2);
472
-		$this->rootView->mkdir($versionsFolder2 . '/folder2');
472
+		$this->rootView->mkdir($versionsFolder2.'/folder2');
473 473
 		// create some versions
474
-		$v1 = $versionsFolder2 . '/folder2/test.txt.v' . $t1;
475
-		$v2 = $versionsFolder2 . '/folder2/test.txt.v' . $t2;
474
+		$v1 = $versionsFolder2.'/folder2/test.txt.v'.$t1;
475
+		$v2 = $versionsFolder2.'/folder2/test.txt.v'.$t2;
476 476
 
477 477
 		$this->rootView->file_put_contents($v1, 'version1');
478 478
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -485,10 +485,10 @@  discard block
 block discarded – undo
485 485
 
486 486
 		self::loginHelper(self::TEST_VERSIONS_USER);
487 487
 
488
-		$versionsFolder1 = '/' . self::TEST_VERSIONS_USER . '/files_versions';
488
+		$versionsFolder1 = '/'.self::TEST_VERSIONS_USER.'/files_versions';
489 489
 
490
-		$v1Renamed = $versionsFolder1 . '/folder1/folder2/test.txt.v' . $t1;
491
-		$v2Renamed = $versionsFolder1 . '/folder1/folder2/test.txt.v' . $t2;
490
+		$v1Renamed = $versionsFolder1.'/folder1/folder2/test.txt.v'.$t1;
491
+		$v2Renamed = $versionsFolder1.'/folder1/folder2/test.txt.v'.$t2;
492 492
 
493 493
 		$this->assertTrue($this->rootView->file_exists($v1Renamed));
494 494
 		$this->assertTrue($this->rootView->file_exists($v2Renamed));
@@ -506,11 +506,11 @@  discard block
 block discarded – undo
506 506
 
507 507
 		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT);
508 508
 		// create some versions
509
-		$v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
510
-		$v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
509
+		$v1 = self::USERS_VERSIONS_ROOT.'/test.txt.v'.$t1;
510
+		$v2 = self::USERS_VERSIONS_ROOT.'/test.txt.v'.$t2;
511 511
 		// the renamed versions should not exist! Because we only moved the mount point!
512
-		$v1Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
513
-		$v2Renamed = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
512
+		$v1Renamed = self::USERS_VERSIONS_ROOT.'/test2.txt.v'.$t1;
513
+		$v2Renamed = self::USERS_VERSIONS_ROOT.'/test2.txt.v'.$t2;
514 514
 
515 515
 		$this->rootView->file_put_contents($v1, 'version1');
516 516
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -554,10 +554,10 @@  discard block
 block discarded – undo
554 554
 		$t2 = $t1 - 60 * 60 * 24 * 14;
555 555
 
556 556
 		// create some versions
557
-		$v1 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t1;
558
-		$v2 = self::USERS_VERSIONS_ROOT . '/test.txt.v' . $t2;
559
-		$v1Copied = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t1;
560
-		$v2Copied = self::USERS_VERSIONS_ROOT . '/test2.txt.v' . $t2;
557
+		$v1 = self::USERS_VERSIONS_ROOT.'/test.txt.v'.$t1;
558
+		$v2 = self::USERS_VERSIONS_ROOT.'/test.txt.v'.$t2;
559
+		$v1Copied = self::USERS_VERSIONS_ROOT.'/test2.txt.v'.$t1;
560
+		$v2Copied = self::USERS_VERSIONS_ROOT.'/test2.txt.v'.$t2;
561 561
 
562 562
 		$this->rootView->file_put_contents($v1, 'version1');
563 563
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -585,10 +585,10 @@  discard block
 block discarded – undo
585 585
 		$t2 = $t1 - 60 * 60 * 24 * 14;
586 586
 
587 587
 		// create some versions
588
-		$v1 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t1;
589
-		$v2 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t2;
588
+		$v1 = self::USERS_VERSIONS_ROOT.'/subfolder/test.txt.v'.$t1;
589
+		$v2 = self::USERS_VERSIONS_ROOT.'/subfolder/test.txt.v'.$t2;
590 590
 
591
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/subfolder/');
591
+		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT.'/subfolder/');
592 592
 
593 593
 		$this->rootView->file_put_contents($v1, 'version1');
594 594
 		$this->rootView->file_put_contents($v2, 'version2');
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
 		}
605 605
 
606 606
 		//cleanup
607
-		$this->rootView->deleteAll(self::USERS_VERSIONS_ROOT . '/subfolder');
607
+		$this->rootView->deleteAll(self::USERS_VERSIONS_ROOT.'/subfolder');
608 608
 	}
609 609
 
610 610
 	/**
@@ -647,7 +647,7 @@  discard block
 block discarded – undo
647 647
 
648 648
 	public function testRestoreCrossStorage(): void {
649 649
 		$storage2 = new Temporary([]);
650
-		Filesystem::mount($storage2, [], self::TEST_VERSIONS_USER . '/files/sub');
650
+		Filesystem::mount($storage2, [], self::TEST_VERSIONS_USER.'/files/sub');
651 651
 
652 652
 		$this->doTestRestore();
653 653
 	}
@@ -746,7 +746,7 @@  discard block
 block discarded – undo
746 746
 		$eventHandler->expects($this->any())
747 747
 			->method('callback')
748 748
 			->willReturnCallback(
749
-				function ($p) use (&$params): void {
749
+				function($p) use (&$params): void {
750 750
 					$params = $p;
751 751
 				}
752 752
 			);
@@ -760,7 +760,7 @@  discard block
 block discarded – undo
760 760
 	}
761 761
 
762 762
 	private function doTestRestore() {
763
-		$filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt';
763
+		$filePath = self::TEST_VERSIONS_USER.'/files/sub/test.txt';
764 764
 		$this->rootView->file_put_contents($filePath, 'test file');
765 765
 
766 766
 		$fileInfo = $this->rootView->getFileInfo($filePath);
@@ -772,10 +772,10 @@  discard block
 block discarded – undo
772 772
 		$t2 = $t1 - 60 * 60 * 24 * 14;
773 773
 
774 774
 		// create some versions
775
-		$v1 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t1;
776
-		$v2 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t2;
775
+		$v1 = self::USERS_VERSIONS_ROOT.'/sub/test.txt.v'.$t1;
776
+		$v2 = self::USERS_VERSIONS_ROOT.'/sub/test.txt.v'.$t2;
777 777
 
778
-		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/sub');
778
+		$this->rootView->mkdir(self::USERS_VERSIONS_ROOT.'/sub');
779 779
 
780 780
 		$this->rootView->file_put_contents($v1, 'version1');
781 781
 		$fileInfoV1 = $this->rootView->getFileInfo($v1);
@@ -808,7 +808,7 @@  discard block
 block discarded – undo
808 808
 
809 809
 		$eventDispatcher = Server::get(IEventDispatcher::class);
810 810
 		$eventFired = false;
811
-		$eventDispatcher->addListener(VersionRestoredEvent::class, function ($event) use (&$eventFired, $t2): void {
811
+		$eventDispatcher->addListener(VersionRestoredEvent::class, function($event) use (&$eventFired, $t2): void {
812 812
 			$eventFired = true;
813 813
 			$this->assertEquals('/sub/test.txt', $event->getVersion()->getVersionPath());
814 814
 			$this->assertTrue($event->getVersion()->getRevisionId() > 0);
@@ -816,7 +816,7 @@  discard block
 block discarded – undo
816 816
 
817 817
 		$versionManager = Server::get(IVersionManager::class);
818 818
 		$versions = $versionManager->getVersionsForFile($this->user1, $info1);
819
-		$version = array_filter($versions, function ($version) use ($t2) {
819
+		$version = array_filter($versions, function($version) use ($t2) {
820 820
 			return $version->getRevisionId() === $t2;
821 821
 		});
822 822
 		$this->assertTrue($versionManager->rollback(current($version)));
@@ -847,7 +847,7 @@  discard block
 block discarded – undo
847 847
 		);
848 848
 
849 849
 		$this->assertTrue(
850
-			$this->rootView->file_exists(self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t0),
850
+			$this->rootView->file_exists(self::USERS_VERSIONS_ROOT.'/sub/test.txt.v'.$t0),
851 851
 			'A version file was created for the file before restoration'
852 852
 		);
853 853
 		$this->assertTrue(
@@ -862,15 +862,15 @@  discard block
 block discarded – undo
862 862
 		$this->assertCount(2, $newVersions, 'Additional version created');
863 863
 
864 864
 		$this->assertTrue(
865
-			isset($newVersions[$t0 . '#' . 'test.txt']),
865
+			isset($newVersions[$t0.'#'.'test.txt']),
866 866
 			'A version was created for the file before restoration'
867 867
 		);
868 868
 		$this->assertTrue(
869
-			isset($newVersions[$t1 . '#' . 'test.txt']),
869
+			isset($newVersions[$t1.'#'.'test.txt']),
870 870
 			'Untouched version is still there'
871 871
 		);
872 872
 		$this->assertFalse(
873
-			isset($newVersions[$t2 . '#' . 'test.txt']),
873
+			isset($newVersions[$t2.'#'.'test.txt']),
874 874
 			'Restored version is not in the list any more'
875 875
 		);
876 876
 	}
@@ -930,7 +930,7 @@  discard block
 block discarded – undo
930 930
 		// needed to make the hooks fire
931 931
 		\OC_Util::setupFS(self::TEST_VERSIONS_USER);
932 932
 
933
-		$userView = new View('/' . self::TEST_VERSIONS_USER . '/files');
933
+		$userView = new View('/'.self::TEST_VERSIONS_USER.'/files');
934 934
 		$this->createAndCheckVersions(
935 935
 			$userView,
936 936
 			'test.txt'
@@ -949,11 +949,11 @@  discard block
 block discarded – undo
949 949
 		$this->loginAsUser(self::TEST_VERSIONS_USER);
950 950
 
951 951
 		// need to scan for the versions
952
-		[$rootStorage,] = $this->rootView->resolvePath(self::TEST_VERSIONS_USER . '/files_versions');
952
+		[$rootStorage, ] = $this->rootView->resolvePath(self::TEST_VERSIONS_USER.'/files_versions');
953 953
 		$rootStorage->getScanner()->scan('files_versions');
954 954
 
955 955
 		$versions = Storage::getVersions(
956
-			self::TEST_VERSIONS_USER, '/' . $path
956
+			self::TEST_VERSIONS_USER, '/'.$path
957 957
 		);
958 958
 
959 959
 		// note: we cannot predict how many versions are created due to
Please login to merge, or discard this patch.
apps/settings/lib/Settings/Admin/Mail.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -13,71 +13,71 @@
 block discarded – undo
13 13
 use OCP\Settings\IDelegatedSettings;
14 14
 
15 15
 class Mail implements IDelegatedSettings {
16
-	/**
17
-	 * @param IConfig $config
18
-	 * @param IL10N $l
19
-	 */
20
-	public function __construct(
21
-		private IConfig $config,
22
-		private IL10N $l,
23
-	) {
24
-	}
16
+    /**
17
+     * @param IConfig $config
18
+     * @param IL10N $l
19
+     */
20
+    public function __construct(
21
+        private IConfig $config,
22
+        private IL10N $l,
23
+    ) {
24
+    }
25 25
 
26
-	/**
27
-	 * @return TemplateResponse
28
-	 */
29
-	public function getForm() {
30
-		$finder = Server::get(IBinaryFinder::class);
26
+    /**
27
+     * @return TemplateResponse
28
+     */
29
+    public function getForm() {
30
+        $finder = Server::get(IBinaryFinder::class);
31 31
 
32
-		$parameters = [
33
-			// Mail
34
-			'sendmail_is_available' => $finder->findBinaryPath('sendmail') !== false,
35
-			'mail_domain' => $this->config->getSystemValue('mail_domain', ''),
36
-			'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''),
37
-			'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''),
38
-			'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''),
39
-			'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''),
40
-			'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''),
41
-			'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false),
42
-			'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''),
43
-			'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''),
44
-			'mail_sendmailmode' => $this->config->getSystemValue('mail_sendmailmode', 'smtp'),
45
-		];
32
+        $parameters = [
33
+            // Mail
34
+            'sendmail_is_available' => $finder->findBinaryPath('sendmail') !== false,
35
+            'mail_domain' => $this->config->getSystemValue('mail_domain', ''),
36
+            'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''),
37
+            'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''),
38
+            'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''),
39
+            'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''),
40
+            'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''),
41
+            'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false),
42
+            'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''),
43
+            'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''),
44
+            'mail_sendmailmode' => $this->config->getSystemValue('mail_sendmailmode', 'smtp'),
45
+        ];
46 46
 
47
-		if ($parameters['mail_smtppassword'] !== '') {
48
-			$parameters['mail_smtppassword'] = '********';
49
-		}
47
+        if ($parameters['mail_smtppassword'] !== '') {
48
+            $parameters['mail_smtppassword'] = '********';
49
+        }
50 50
 
51
-		if ($parameters['mail_smtpmode'] === '' || $parameters['mail_smtpmode'] === 'php') {
52
-			$parameters['mail_smtpmode'] = 'smtp';
53
-		}
51
+        if ($parameters['mail_smtpmode'] === '' || $parameters['mail_smtpmode'] === 'php') {
52
+            $parameters['mail_smtpmode'] = 'smtp';
53
+        }
54 54
 
55
-		return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, '');
56
-	}
55
+        return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, '');
56
+    }
57 57
 
58
-	/**
59
-	 * @return string the section ID, e.g. 'sharing'
60
-	 */
61
-	public function getSection() {
62
-		return 'server';
63
-	}
58
+    /**
59
+     * @return string the section ID, e.g. 'sharing'
60
+     */
61
+    public function getSection() {
62
+        return 'server';
63
+    }
64 64
 
65
-	/**
66
-	 * @return int whether the form should be rather on the top or bottom of
67
-	 *             the admin section. The forms are arranged in ascending order of the
68
-	 *             priority values. It is required to return a value between 0 and 100.
69
-	 *
70
-	 * E.g.: 70
71
-	 */
72
-	public function getPriority() {
73
-		return 10;
74
-	}
65
+    /**
66
+     * @return int whether the form should be rather on the top or bottom of
67
+     *             the admin section. The forms are arranged in ascending order of the
68
+     *             priority values. It is required to return a value between 0 and 100.
69
+     *
70
+     * E.g.: 70
71
+     */
72
+    public function getPriority() {
73
+        return 10;
74
+    }
75 75
 
76
-	public function getName(): ?string {
77
-		return $this->l->t('Email server');
78
-	}
76
+    public function getName(): ?string {
77
+        return $this->l->t('Email server');
78
+    }
79 79
 
80
-	public function getAuthorizedAppConfig(): array {
81
-		return [];
82
-	}
80
+    public function getAuthorizedAppConfig(): array {
81
+        return [];
82
+    }
83 83
 }
Please login to merge, or discard this patch.
apps/settings/lib/Settings/Personal/PersonalInfo.php 1 patch
Indentation   +283 added lines, -283 removed lines patch added patch discarded remove patch
@@ -33,287 +33,287 @@
 block discarded – undo
33 33
 
34 34
 class PersonalInfo implements ISettings {
35 35
 
36
-	/** @var ProfileManager */
37
-	private $profileManager;
38
-
39
-	public function __construct(
40
-		private IConfig $config,
41
-		private IUserManager $userManager,
42
-		private IGroupManager $groupManager,
43
-		private IAccountManager $accountManager,
44
-		ProfileManager $profileManager,
45
-		private IAppManager $appManager,
46
-		private IFactory $l10nFactory,
47
-		private IL10N $l,
48
-		private IInitialState $initialStateService,
49
-		private IManager $manager,
50
-	) {
51
-		$this->profileManager = $profileManager;
52
-	}
53
-
54
-	public function getForm(): TemplateResponse {
55
-		$federationEnabled = $this->appManager->isEnabledForUser('federation');
56
-		$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
57
-		$lookupServerUploadEnabled = false;
58
-		if ($federatedFileSharingEnabled) {
59
-			/** @var FederatedShareProvider $shareProvider */
60
-			$shareProvider = Server::get(FederatedShareProvider::class);
61
-			$lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
62
-		}
63
-
64
-		$uid = \OC_User::getUser();
65
-		$user = $this->userManager->get($uid);
66
-		$account = $this->accountManager->getAccount($user);
67
-
68
-		// make sure FS is setup before querying storage related stuff...
69
-		\OC_Util::setupFS($user->getUID());
70
-
71
-		$storageInfo = \OC_Helper::getStorageInfo('/');
72
-		if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
73
-			$totalSpace = $this->l->t('Unlimited');
74
-		} else {
75
-			$totalSpace = Util::humanFileSize($storageInfo['total']);
76
-		}
77
-
78
-		$messageParameters = $this->getMessageParameters($account);
79
-
80
-		$parameters = [
81
-			'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
82
-			'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(),
83
-			'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(),
84
-		] + $messageParameters;
85
-
86
-		$personalInfoParameters = [
87
-			'userId' => $uid,
88
-			'avatar' => $this->getProperty($account, IAccountManager::PROPERTY_AVATAR),
89
-			'groups' => $this->getGroups($user),
90
-			'quota' => $storageInfo['quota'],
91
-			'totalSpace' => $totalSpace,
92
-			'usage' => Util::humanFileSize($storageInfo['used']),
93
-			'usageRelative' => round($storageInfo['relative']),
94
-			'displayName' => $this->getProperty($account, IAccountManager::PROPERTY_DISPLAYNAME),
95
-			'emailMap' => $this->getEmailMap($account),
96
-			'phone' => $this->getProperty($account, IAccountManager::PROPERTY_PHONE),
97
-			'defaultPhoneRegion' => $this->config->getSystemValueString('default_phone_region'),
98
-			'location' => $this->getProperty($account, IAccountManager::PROPERTY_ADDRESS),
99
-			'website' => $this->getProperty($account, IAccountManager::PROPERTY_WEBSITE),
100
-			'twitter' => $this->getProperty($account, IAccountManager::PROPERTY_TWITTER),
101
-			'fediverse' => $this->getProperty($account, IAccountManager::PROPERTY_FEDIVERSE),
102
-			'languageMap' => $this->getLanguageMap($user),
103
-			'localeMap' => $this->getLocaleMap($user),
104
-			'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(),
105
-			'profileEnabled' => $this->profileManager->isProfileEnabled($user),
106
-			'organisation' => $this->getProperty($account, IAccountManager::PROPERTY_ORGANISATION),
107
-			'role' => $this->getProperty($account, IAccountManager::PROPERTY_ROLE),
108
-			'headline' => $this->getProperty($account, IAccountManager::PROPERTY_HEADLINE),
109
-			'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY),
110
-			'birthdate' => $this->getProperty($account, IAccountManager::PROPERTY_BIRTHDATE),
111
-			'firstDayOfWeek' => $this->config->getUserValue($uid, 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK),
112
-			'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS),
113
-		];
114
-
115
-		$accountParameters = [
116
-			'avatarChangeSupported' => $user->canChangeAvatar(),
117
-			'displayNameChangeSupported' => $user->canChangeDisplayName(),
118
-			'emailChangeSupported' => $user->canChangeEmail(),
119
-			'federationEnabled' => $federationEnabled,
120
-			'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
121
-		];
122
-
123
-		$profileParameters = [
124
-			'profileConfig' => $this->profileManager->getProfileConfigWithMetadata($user, $user),
125
-		];
126
-
127
-		$this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled());
128
-		$this->initialStateService->provideInitialState('personalInfoParameters', $personalInfoParameters);
129
-		$this->initialStateService->provideInitialState('accountParameters', $accountParameters);
130
-		$this->initialStateService->provideInitialState('profileParameters', $profileParameters);
131
-
132
-		return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
133
-	}
134
-
135
-	/**
136
-	 * Check if is fair use of free push service
137
-	 * @return boolean
138
-	 */
139
-	private function isFairUseOfFreePushService(): bool {
140
-		return $this->manager->isFairUseOfFreePushService();
141
-	}
142
-
143
-	/**
144
-	 * returns the property data in an
145
-	 * associative array
146
-	 */
147
-	private function getProperty(IAccount $account, string $property): array {
148
-		$property = [
149
-			'name' => $account->getProperty($property)->getName(),
150
-			'value' => $account->getProperty($property)->getValue(),
151
-			'scope' => $account->getProperty($property)->getScope(),
152
-			'verified' => $account->getProperty($property)->getVerified(),
153
-		];
154
-
155
-		return $property;
156
-	}
157
-
158
-	/**
159
-	 * returns the section ID string, e.g. 'sharing'
160
-	 * @since 9.1
161
-	 */
162
-	public function getSection(): string {
163
-		return 'personal-info';
164
-	}
165
-
166
-	/**
167
-	 * @return int whether the form should be rather on the top or bottom of
168
-	 *             the admin section. The forms are arranged in ascending order of the
169
-	 *             priority values. It is required to return a value between 0 and 100.
170
-	 *
171
-	 * E.g.: 70
172
-	 * @since 9.1
173
-	 */
174
-	public function getPriority(): int {
175
-		return 10;
176
-	}
177
-
178
-	/**
179
-	 * returns a sorted list of the user's group GIDs
180
-	 */
181
-	private function getGroups(IUser $user): array {
182
-		$groups = array_map(
183
-			static function (IGroup $group) {
184
-				return $group->getDisplayName();
185
-			},
186
-			$this->groupManager->getUserGroups($user)
187
-		);
188
-		sort($groups);
189
-
190
-		return $groups;
191
-	}
192
-
193
-	/**
194
-	 * returns the primary email and additional emails in an
195
-	 * associative array
196
-	 */
197
-	private function getEmailMap(IAccount $account): array {
198
-		$systemEmail = [
199
-			'name' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getName(),
200
-			'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
201
-			'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
202
-			'verified' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
203
-		];
204
-
205
-		$additionalEmails = array_map(
206
-			function (IAccountProperty $property) {
207
-				return [
208
-					'name' => $property->getName(),
209
-					'value' => $property->getValue(),
210
-					'scope' => $property->getScope(),
211
-					'verified' => $property->getVerified(),
212
-					'locallyVerified' => $property->getLocallyVerified(),
213
-				];
214
-			},
215
-			$account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)->getProperties(),
216
-		);
217
-
218
-		$emailMap = [
219
-			'primaryEmail' => $systemEmail,
220
-			'additionalEmails' => $additionalEmails,
221
-			'notificationEmail' => (string)$account->getUser()->getPrimaryEMailAddress(),
222
-		];
223
-
224
-		return $emailMap;
225
-	}
226
-
227
-	/**
228
-	 * returns the user's active language, common languages, and other languages in an
229
-	 * associative array
230
-	 */
231
-	private function getLanguageMap(IUser $user): array {
232
-		$forceLanguage = $this->config->getSystemValue('force_language', false);
233
-		if ($forceLanguage !== false) {
234
-			return [];
235
-		}
236
-
237
-		$uid = $user->getUID();
238
-
239
-		$userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
240
-		$languages = $this->l10nFactory->getLanguages();
241
-
242
-		// associate the user language with the proper array
243
-		$userLangIndex = array_search($userConfLang, array_column($languages['commonLanguages'], 'code'));
244
-		$userLang = $languages['commonLanguages'][$userLangIndex];
245
-		// search in the other languages
246
-		if ($userLangIndex === false) {
247
-			$userLangIndex = array_search($userConfLang, array_column($languages['otherLanguages'], 'code'));
248
-			$userLang = $languages['otherLanguages'][$userLangIndex];
249
-		}
250
-		// if user language is not available but set somehow: show the actual code as name
251
-		if (!is_array($userLang)) {
252
-			$userLang = [
253
-				'code' => $userConfLang,
254
-				'name' => $userConfLang,
255
-			];
256
-		}
257
-
258
-		return array_merge(
259
-			['activeLanguage' => $userLang],
260
-			$languages
261
-		);
262
-	}
263
-
264
-	private function getLocaleMap(IUser $user): array {
265
-		$forceLanguage = $this->config->getSystemValue('force_locale', false);
266
-		if ($forceLanguage !== false) {
267
-			return [];
268
-		}
269
-
270
-		$uid = $user->getUID();
271
-		$userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
272
-		$userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale($userLang));
273
-		$localeCodes = $this->l10nFactory->findAvailableLocales();
274
-		$userLocale = array_filter($localeCodes, fn ($value) => $userLocaleString === $value['code']);
275
-
276
-		if (!empty($userLocale)) {
277
-			$userLocale = reset($userLocale);
278
-		}
279
-
280
-		$localesForLanguage = array_values(array_filter($localeCodes, fn ($localeCode) => str_starts_with($localeCode['code'], $userLang)));
281
-		$otherLocales = array_values(array_filter($localeCodes, fn ($localeCode) => !str_starts_with($localeCode['code'], $userLang)));
282
-
283
-		if (!$userLocale) {
284
-			$userLocale = [
285
-				'code' => 'en',
286
-				'name' => 'English'
287
-			];
288
-		}
289
-
290
-		return [
291
-			'activeLocaleLang' => $userLocaleString,
292
-			'activeLocale' => $userLocale,
293
-			'localesForLanguage' => $localesForLanguage,
294
-			'otherLocales' => $otherLocales,
295
-		];
296
-	}
297
-
298
-	/**
299
-	 * returns the message parameters
300
-	 */
301
-	private function getMessageParameters(IAccount $account): array {
302
-		$needVerifyMessage = [IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER];
303
-		$messageParameters = [];
304
-		foreach ($needVerifyMessage as $property) {
305
-			switch ($account->getProperty($property)->getVerified()) {
306
-				case IAccountManager::VERIFIED:
307
-					$message = $this->l->t('Verifying');
308
-					break;
309
-				case IAccountManager::VERIFICATION_IN_PROGRESS:
310
-					$message = $this->l->t('Verifying …');
311
-					break;
312
-				default:
313
-					$message = $this->l->t('Verify');
314
-			}
315
-			$messageParameters[$property . 'Message'] = $message;
316
-		}
317
-		return $messageParameters;
318
-	}
36
+    /** @var ProfileManager */
37
+    private $profileManager;
38
+
39
+    public function __construct(
40
+        private IConfig $config,
41
+        private IUserManager $userManager,
42
+        private IGroupManager $groupManager,
43
+        private IAccountManager $accountManager,
44
+        ProfileManager $profileManager,
45
+        private IAppManager $appManager,
46
+        private IFactory $l10nFactory,
47
+        private IL10N $l,
48
+        private IInitialState $initialStateService,
49
+        private IManager $manager,
50
+    ) {
51
+        $this->profileManager = $profileManager;
52
+    }
53
+
54
+    public function getForm(): TemplateResponse {
55
+        $federationEnabled = $this->appManager->isEnabledForUser('federation');
56
+        $federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
57
+        $lookupServerUploadEnabled = false;
58
+        if ($federatedFileSharingEnabled) {
59
+            /** @var FederatedShareProvider $shareProvider */
60
+            $shareProvider = Server::get(FederatedShareProvider::class);
61
+            $lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
62
+        }
63
+
64
+        $uid = \OC_User::getUser();
65
+        $user = $this->userManager->get($uid);
66
+        $account = $this->accountManager->getAccount($user);
67
+
68
+        // make sure FS is setup before querying storage related stuff...
69
+        \OC_Util::setupFS($user->getUID());
70
+
71
+        $storageInfo = \OC_Helper::getStorageInfo('/');
72
+        if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
73
+            $totalSpace = $this->l->t('Unlimited');
74
+        } else {
75
+            $totalSpace = Util::humanFileSize($storageInfo['total']);
76
+        }
77
+
78
+        $messageParameters = $this->getMessageParameters($account);
79
+
80
+        $parameters = [
81
+            'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
82
+            'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(),
83
+            'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(),
84
+        ] + $messageParameters;
85
+
86
+        $personalInfoParameters = [
87
+            'userId' => $uid,
88
+            'avatar' => $this->getProperty($account, IAccountManager::PROPERTY_AVATAR),
89
+            'groups' => $this->getGroups($user),
90
+            'quota' => $storageInfo['quota'],
91
+            'totalSpace' => $totalSpace,
92
+            'usage' => Util::humanFileSize($storageInfo['used']),
93
+            'usageRelative' => round($storageInfo['relative']),
94
+            'displayName' => $this->getProperty($account, IAccountManager::PROPERTY_DISPLAYNAME),
95
+            'emailMap' => $this->getEmailMap($account),
96
+            'phone' => $this->getProperty($account, IAccountManager::PROPERTY_PHONE),
97
+            'defaultPhoneRegion' => $this->config->getSystemValueString('default_phone_region'),
98
+            'location' => $this->getProperty($account, IAccountManager::PROPERTY_ADDRESS),
99
+            'website' => $this->getProperty($account, IAccountManager::PROPERTY_WEBSITE),
100
+            'twitter' => $this->getProperty($account, IAccountManager::PROPERTY_TWITTER),
101
+            'fediverse' => $this->getProperty($account, IAccountManager::PROPERTY_FEDIVERSE),
102
+            'languageMap' => $this->getLanguageMap($user),
103
+            'localeMap' => $this->getLocaleMap($user),
104
+            'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(),
105
+            'profileEnabled' => $this->profileManager->isProfileEnabled($user),
106
+            'organisation' => $this->getProperty($account, IAccountManager::PROPERTY_ORGANISATION),
107
+            'role' => $this->getProperty($account, IAccountManager::PROPERTY_ROLE),
108
+            'headline' => $this->getProperty($account, IAccountManager::PROPERTY_HEADLINE),
109
+            'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY),
110
+            'birthdate' => $this->getProperty($account, IAccountManager::PROPERTY_BIRTHDATE),
111
+            'firstDayOfWeek' => $this->config->getUserValue($uid, 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK),
112
+            'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS),
113
+        ];
114
+
115
+        $accountParameters = [
116
+            'avatarChangeSupported' => $user->canChangeAvatar(),
117
+            'displayNameChangeSupported' => $user->canChangeDisplayName(),
118
+            'emailChangeSupported' => $user->canChangeEmail(),
119
+            'federationEnabled' => $federationEnabled,
120
+            'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
121
+        ];
122
+
123
+        $profileParameters = [
124
+            'profileConfig' => $this->profileManager->getProfileConfigWithMetadata($user, $user),
125
+        ];
126
+
127
+        $this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled());
128
+        $this->initialStateService->provideInitialState('personalInfoParameters', $personalInfoParameters);
129
+        $this->initialStateService->provideInitialState('accountParameters', $accountParameters);
130
+        $this->initialStateService->provideInitialState('profileParameters', $profileParameters);
131
+
132
+        return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
133
+    }
134
+
135
+    /**
136
+     * Check if is fair use of free push service
137
+     * @return boolean
138
+     */
139
+    private function isFairUseOfFreePushService(): bool {
140
+        return $this->manager->isFairUseOfFreePushService();
141
+    }
142
+
143
+    /**
144
+     * returns the property data in an
145
+     * associative array
146
+     */
147
+    private function getProperty(IAccount $account, string $property): array {
148
+        $property = [
149
+            'name' => $account->getProperty($property)->getName(),
150
+            'value' => $account->getProperty($property)->getValue(),
151
+            'scope' => $account->getProperty($property)->getScope(),
152
+            'verified' => $account->getProperty($property)->getVerified(),
153
+        ];
154
+
155
+        return $property;
156
+    }
157
+
158
+    /**
159
+     * returns the section ID string, e.g. 'sharing'
160
+     * @since 9.1
161
+     */
162
+    public function getSection(): string {
163
+        return 'personal-info';
164
+    }
165
+
166
+    /**
167
+     * @return int whether the form should be rather on the top or bottom of
168
+     *             the admin section. The forms are arranged in ascending order of the
169
+     *             priority values. It is required to return a value between 0 and 100.
170
+     *
171
+     * E.g.: 70
172
+     * @since 9.1
173
+     */
174
+    public function getPriority(): int {
175
+        return 10;
176
+    }
177
+
178
+    /**
179
+     * returns a sorted list of the user's group GIDs
180
+     */
181
+    private function getGroups(IUser $user): array {
182
+        $groups = array_map(
183
+            static function (IGroup $group) {
184
+                return $group->getDisplayName();
185
+            },
186
+            $this->groupManager->getUserGroups($user)
187
+        );
188
+        sort($groups);
189
+
190
+        return $groups;
191
+    }
192
+
193
+    /**
194
+     * returns the primary email and additional emails in an
195
+     * associative array
196
+     */
197
+    private function getEmailMap(IAccount $account): array {
198
+        $systemEmail = [
199
+            'name' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getName(),
200
+            'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
201
+            'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
202
+            'verified' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(),
203
+        ];
204
+
205
+        $additionalEmails = array_map(
206
+            function (IAccountProperty $property) {
207
+                return [
208
+                    'name' => $property->getName(),
209
+                    'value' => $property->getValue(),
210
+                    'scope' => $property->getScope(),
211
+                    'verified' => $property->getVerified(),
212
+                    'locallyVerified' => $property->getLocallyVerified(),
213
+                ];
214
+            },
215
+            $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)->getProperties(),
216
+        );
217
+
218
+        $emailMap = [
219
+            'primaryEmail' => $systemEmail,
220
+            'additionalEmails' => $additionalEmails,
221
+            'notificationEmail' => (string)$account->getUser()->getPrimaryEMailAddress(),
222
+        ];
223
+
224
+        return $emailMap;
225
+    }
226
+
227
+    /**
228
+     * returns the user's active language, common languages, and other languages in an
229
+     * associative array
230
+     */
231
+    private function getLanguageMap(IUser $user): array {
232
+        $forceLanguage = $this->config->getSystemValue('force_language', false);
233
+        if ($forceLanguage !== false) {
234
+            return [];
235
+        }
236
+
237
+        $uid = $user->getUID();
238
+
239
+        $userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
240
+        $languages = $this->l10nFactory->getLanguages();
241
+
242
+        // associate the user language with the proper array
243
+        $userLangIndex = array_search($userConfLang, array_column($languages['commonLanguages'], 'code'));
244
+        $userLang = $languages['commonLanguages'][$userLangIndex];
245
+        // search in the other languages
246
+        if ($userLangIndex === false) {
247
+            $userLangIndex = array_search($userConfLang, array_column($languages['otherLanguages'], 'code'));
248
+            $userLang = $languages['otherLanguages'][$userLangIndex];
249
+        }
250
+        // if user language is not available but set somehow: show the actual code as name
251
+        if (!is_array($userLang)) {
252
+            $userLang = [
253
+                'code' => $userConfLang,
254
+                'name' => $userConfLang,
255
+            ];
256
+        }
257
+
258
+        return array_merge(
259
+            ['activeLanguage' => $userLang],
260
+            $languages
261
+        );
262
+    }
263
+
264
+    private function getLocaleMap(IUser $user): array {
265
+        $forceLanguage = $this->config->getSystemValue('force_locale', false);
266
+        if ($forceLanguage !== false) {
267
+            return [];
268
+        }
269
+
270
+        $uid = $user->getUID();
271
+        $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
272
+        $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale($userLang));
273
+        $localeCodes = $this->l10nFactory->findAvailableLocales();
274
+        $userLocale = array_filter($localeCodes, fn ($value) => $userLocaleString === $value['code']);
275
+
276
+        if (!empty($userLocale)) {
277
+            $userLocale = reset($userLocale);
278
+        }
279
+
280
+        $localesForLanguage = array_values(array_filter($localeCodes, fn ($localeCode) => str_starts_with($localeCode['code'], $userLang)));
281
+        $otherLocales = array_values(array_filter($localeCodes, fn ($localeCode) => !str_starts_with($localeCode['code'], $userLang)));
282
+
283
+        if (!$userLocale) {
284
+            $userLocale = [
285
+                'code' => 'en',
286
+                'name' => 'English'
287
+            ];
288
+        }
289
+
290
+        return [
291
+            'activeLocaleLang' => $userLocaleString,
292
+            'activeLocale' => $userLocale,
293
+            'localesForLanguage' => $localesForLanguage,
294
+            'otherLocales' => $otherLocales,
295
+        ];
296
+    }
297
+
298
+    /**
299
+     * returns the message parameters
300
+     */
301
+    private function getMessageParameters(IAccount $account): array {
302
+        $needVerifyMessage = [IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER];
303
+        $messageParameters = [];
304
+        foreach ($needVerifyMessage as $property) {
305
+            switch ($account->getProperty($property)->getVerified()) {
306
+                case IAccountManager::VERIFIED:
307
+                    $message = $this->l->t('Verifying');
308
+                    break;
309
+                case IAccountManager::VERIFICATION_IN_PROGRESS:
310
+                    $message = $this->l->t('Verifying …');
311
+                    break;
312
+                default:
313
+                    $message = $this->l->t('Verify');
314
+            }
315
+            $messageParameters[$property . 'Message'] = $message;
316
+        }
317
+        return $messageParameters;
318
+    }
319 319
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/External/Scanner.php 1 patch
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -13,42 +13,42 @@
 block discarded – undo
13 13
 use OCP\Files\StorageNotAvailableException;
14 14
 
15 15
 class Scanner extends \OC\Files\Cache\Scanner {
16
-	/** @var Storage */
17
-	protected $storage;
16
+    /** @var Storage */
17
+    protected $storage;
18 18
 
19
-	public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) {
20
-		// Disable locking for federated shares
21
-		parent::scan($path, $recursive, $reuse, false);
22
-	}
19
+    public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) {
20
+        // Disable locking for federated shares
21
+        parent::scan($path, $recursive, $reuse, false);
22
+    }
23 23
 
24
-	/**
25
-	 * Scan a single file and store it in the cache.
26
-	 * If an exception happened while accessing the external storage,
27
-	 * the storage will be checked for availability and removed
28
-	 * if it is not available any more.
29
-	 *
30
-	 * @param string $file file to scan
31
-	 * @param int $reuseExisting
32
-	 * @param int $parentId
33
-	 * @param CacheEntry|array|null|false $cacheData existing data in the cache for the file to be scanned
34
-	 * @param bool $lock set to false to disable getting an additional read lock during scanning
35
-	 * @param array|null $data the metadata for the file, as returned by the storage
36
-	 * @return array|null an array of metadata of the scanned file
37
-	 */
38
-	public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) {
39
-		try {
40
-			return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock, $data);
41
-		} catch (ForbiddenException $e) {
42
-			$this->storage->checkStorageAvailability();
43
-		} catch (NotFoundException $e) {
44
-			// if the storage isn't found, the call to
45
-			// checkStorageAvailable() will verify it and remove it
46
-			// if appropriate
47
-			$this->storage->checkStorageAvailability();
48
-		} catch (StorageInvalidException $e) {
49
-			$this->storage->checkStorageAvailability();
50
-		} catch (StorageNotAvailableException $e) {
51
-			$this->storage->checkStorageAvailability();
52
-		}
53
-	}
24
+    /**
25
+     * Scan a single file and store it in the cache.
26
+     * If an exception happened while accessing the external storage,
27
+     * the storage will be checked for availability and removed
28
+     * if it is not available any more.
29
+     *
30
+     * @param string $file file to scan
31
+     * @param int $reuseExisting
32
+     * @param int $parentId
33
+     * @param CacheEntry|array|null|false $cacheData existing data in the cache for the file to be scanned
34
+     * @param bool $lock set to false to disable getting an additional read lock during scanning
35
+     * @param array|null $data the metadata for the file, as returned by the storage
36
+     * @return array|null an array of metadata of the scanned file
37
+     */
38
+    public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) {
39
+        try {
40
+            return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock, $data);
41
+        } catch (ForbiddenException $e) {
42
+            $this->storage->checkStorageAvailability();
43
+        } catch (NotFoundException $e) {
44
+            // if the storage isn't found, the call to
45
+            // checkStorageAvailable() will verify it and remove it
46
+            // if appropriate
47
+            $this->storage->checkStorageAvailability();
48
+        } catch (StorageInvalidException $e) {
49
+            $this->storage->checkStorageAvailability();
50
+        } catch (StorageNotAvailableException $e) {
51
+            $this->storage->checkStorageAvailability();
52
+        }
53
+    }
54 54
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Command/CleanUp.php 2 patches
Indentation   +90 added lines, -90 removed lines patch added patch discarded remove patch
@@ -21,98 +21,98 @@
 block discarded – undo
21 21
 
22 22
 class CleanUp extends Command {
23 23
 
24
-	public function __construct(
25
-		protected IRootFolder $rootFolder,
26
-		protected IUserManager $userManager,
27
-		protected IDBConnection $dbConnection,
28
-	) {
29
-		parent::__construct();
30
-	}
24
+    public function __construct(
25
+        protected IRootFolder $rootFolder,
26
+        protected IUserManager $userManager,
27
+        protected IDBConnection $dbConnection,
28
+    ) {
29
+        parent::__construct();
30
+    }
31 31
 
32
-	protected function configure() {
33
-		$this
34
-			->setName('trashbin:cleanup')
35
-			->setDescription('Remove deleted files')
36
-			->addArgument(
37
-				'user_id',
38
-				InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
39
-				'remove deleted files of the given user(s)'
40
-			)
41
-			->addOption(
42
-				'all-users',
43
-				null,
44
-				InputOption::VALUE_NONE,
45
-				'run action on all users'
46
-			);
47
-	}
32
+    protected function configure() {
33
+        $this
34
+            ->setName('trashbin:cleanup')
35
+            ->setDescription('Remove deleted files')
36
+            ->addArgument(
37
+                'user_id',
38
+                InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
39
+                'remove deleted files of the given user(s)'
40
+            )
41
+            ->addOption(
42
+                'all-users',
43
+                null,
44
+                InputOption::VALUE_NONE,
45
+                'run action on all users'
46
+            );
47
+    }
48 48
 
49
-	protected function execute(InputInterface $input, OutputInterface $output): int {
50
-		$users = $input->getArgument('user_id');
51
-		$verbose = $input->getOption('verbose');
52
-		if ((!empty($users)) and ($input->getOption('all-users'))) {
53
-			throw new InvalidOptionException('Either specify a user_id or --all-users');
54
-		} elseif (!empty($users)) {
55
-			foreach ($users as $user) {
56
-				if ($this->userManager->userExists($user)) {
57
-					$output->writeln("Remove deleted files of   <info>$user</info>");
58
-					$this->removeDeletedFiles($user, $output, $verbose);
59
-				} else {
60
-					$output->writeln("<error>Unknown user $user</error>");
61
-					return 1;
62
-				}
63
-			}
64
-		} elseif ($input->getOption('all-users')) {
65
-			$output->writeln('Remove deleted files for all users');
66
-			foreach ($this->userManager->getBackends() as $backend) {
67
-				$name = get_class($backend);
68
-				if ($backend instanceof IUserBackend) {
69
-					$name = $backend->getBackendName();
70
-				}
71
-				$output->writeln("Remove deleted files for users on backend <info>$name</info>");
72
-				$limit = 500;
73
-				$offset = 0;
74
-				do {
75
-					$users = $backend->getUsers('', $limit, $offset);
76
-					foreach ($users as $user) {
77
-						$output->writeln("   <info>$user</info>");
78
-						$this->removeDeletedFiles($user, $output, $verbose);
79
-					}
80
-					$offset += $limit;
81
-				} while (count($users) >= $limit);
82
-			}
83
-		} else {
84
-			throw new InvalidOptionException('Either specify a user_id or --all-users');
85
-		}
86
-		return 0;
87
-	}
49
+    protected function execute(InputInterface $input, OutputInterface $output): int {
50
+        $users = $input->getArgument('user_id');
51
+        $verbose = $input->getOption('verbose');
52
+        if ((!empty($users)) and ($input->getOption('all-users'))) {
53
+            throw new InvalidOptionException('Either specify a user_id or --all-users');
54
+        } elseif (!empty($users)) {
55
+            foreach ($users as $user) {
56
+                if ($this->userManager->userExists($user)) {
57
+                    $output->writeln("Remove deleted files of   <info>$user</info>");
58
+                    $this->removeDeletedFiles($user, $output, $verbose);
59
+                } else {
60
+                    $output->writeln("<error>Unknown user $user</error>");
61
+                    return 1;
62
+                }
63
+            }
64
+        } elseif ($input->getOption('all-users')) {
65
+            $output->writeln('Remove deleted files for all users');
66
+            foreach ($this->userManager->getBackends() as $backend) {
67
+                $name = get_class($backend);
68
+                if ($backend instanceof IUserBackend) {
69
+                    $name = $backend->getBackendName();
70
+                }
71
+                $output->writeln("Remove deleted files for users on backend <info>$name</info>");
72
+                $limit = 500;
73
+                $offset = 0;
74
+                do {
75
+                    $users = $backend->getUsers('', $limit, $offset);
76
+                    foreach ($users as $user) {
77
+                        $output->writeln("   <info>$user</info>");
78
+                        $this->removeDeletedFiles($user, $output, $verbose);
79
+                    }
80
+                    $offset += $limit;
81
+                } while (count($users) >= $limit);
82
+            }
83
+        } else {
84
+            throw new InvalidOptionException('Either specify a user_id or --all-users');
85
+        }
86
+        return 0;
87
+    }
88 88
 
89
-	/**
90
-	 * remove deleted files for the given user
91
-	 */
92
-	protected function removeDeletedFiles(string $uid, OutputInterface $output, bool $verbose): void {
93
-		\OC_Util::tearDownFS();
94
-		\OC_Util::setupFS($uid);
95
-		$path = '/' . $uid . '/files_trashbin';
96
-		if ($this->rootFolder->nodeExists($path)) {
97
-			$node = $this->rootFolder->get($path);
89
+    /**
90
+     * remove deleted files for the given user
91
+     */
92
+    protected function removeDeletedFiles(string $uid, OutputInterface $output, bool $verbose): void {
93
+        \OC_Util::tearDownFS();
94
+        \OC_Util::setupFS($uid);
95
+        $path = '/' . $uid . '/files_trashbin';
96
+        if ($this->rootFolder->nodeExists($path)) {
97
+            $node = $this->rootFolder->get($path);
98 98
 
99
-			if ($verbose) {
100
-				$output->writeln('Deleting <info>' . Util::humanFileSize($node->getSize()) . "</info> in trash for <info>$uid</info>.");
101
-			}
102
-			$node->delete();
103
-			if ($this->rootFolder->nodeExists($path)) {
104
-				$output->writeln('<error>Trash folder sill exists after attempting to delete it</error>');
105
-				return;
106
-			}
107
-			$query = $this->dbConnection->getQueryBuilder();
108
-			$query->delete('files_trash')
109
-				->where($query->expr()->eq('user', $query->createParameter('uid')))
110
-				->setParameter('uid', $uid);
111
-			$query->executeStatement();
112
-		} else {
113
-			if ($verbose) {
114
-				$output->writeln("No trash found for <info>$uid</info>");
115
-			}
116
-		}
117
-	}
99
+            if ($verbose) {
100
+                $output->writeln('Deleting <info>' . Util::humanFileSize($node->getSize()) . "</info> in trash for <info>$uid</info>.");
101
+            }
102
+            $node->delete();
103
+            if ($this->rootFolder->nodeExists($path)) {
104
+                $output->writeln('<error>Trash folder sill exists after attempting to delete it</error>');
105
+                return;
106
+            }
107
+            $query = $this->dbConnection->getQueryBuilder();
108
+            $query->delete('files_trash')
109
+                ->where($query->expr()->eq('user', $query->createParameter('uid')))
110
+                ->setParameter('uid', $uid);
111
+            $query->executeStatement();
112
+        } else {
113
+            if ($verbose) {
114
+                $output->writeln("No trash found for <info>$uid</info>");
115
+            }
116
+        }
117
+    }
118 118
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -92,12 +92,12 @@
 block discarded – undo
92 92
 	protected function removeDeletedFiles(string $uid, OutputInterface $output, bool $verbose): void {
93 93
 		\OC_Util::tearDownFS();
94 94
 		\OC_Util::setupFS($uid);
95
-		$path = '/' . $uid . '/files_trashbin';
95
+		$path = '/'.$uid.'/files_trashbin';
96 96
 		if ($this->rootFolder->nodeExists($path)) {
97 97
 			$node = $this->rootFolder->get($path);
98 98
 
99 99
 			if ($verbose) {
100
-				$output->writeln('Deleting <info>' . Util::humanFileSize($node->getSize()) . "</info> in trash for <info>$uid</info>.");
100
+				$output->writeln('Deleting <info>'.Util::humanFileSize($node->getSize())."</info> in trash for <info>$uid</info>.");
101 101
 			}
102 102
 			$node->delete();
103 103
 			if ($this->rootFolder->nodeExists($path)) {
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Command/Size.php 2 patches
Indentation   +92 added lines, -92 removed lines patch added patch discarded remove patch
@@ -20,105 +20,105 @@
 block discarded – undo
20 20
 use Symfony\Component\Console\Output\OutputInterface;
21 21
 
22 22
 class Size extends Base {
23
-	public function __construct(
24
-		private IConfig $config,
25
-		private IUserManager $userManager,
26
-		private IBus $commandBus,
27
-	) {
28
-		parent::__construct();
29
-	}
23
+    public function __construct(
24
+        private IConfig $config,
25
+        private IUserManager $userManager,
26
+        private IBus $commandBus,
27
+    ) {
28
+        parent::__construct();
29
+    }
30 30
 
31
-	protected function configure() {
32
-		parent::configure();
33
-		$this
34
-			->setName('trashbin:size')
35
-			->setDescription('Configure the target trashbin size')
36
-			->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'configure the target size for the provided user, if no user is given the default size is configured')
37
-			->addArgument(
38
-				'size',
39
-				InputArgument::OPTIONAL,
40
-				'the target size for the trashbin, if not provided the current trashbin size will be returned'
41
-			);
42
-	}
31
+    protected function configure() {
32
+        parent::configure();
33
+        $this
34
+            ->setName('trashbin:size')
35
+            ->setDescription('Configure the target trashbin size')
36
+            ->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'configure the target size for the provided user, if no user is given the default size is configured')
37
+            ->addArgument(
38
+                'size',
39
+                InputArgument::OPTIONAL,
40
+                'the target size for the trashbin, if not provided the current trashbin size will be returned'
41
+            );
42
+    }
43 43
 
44
-	protected function execute(InputInterface $input, OutputInterface $output): int {
45
-		$user = $input->getOption('user');
46
-		$size = $input->getArgument('size');
44
+    protected function execute(InputInterface $input, OutputInterface $output): int {
45
+        $user = $input->getOption('user');
46
+        $size = $input->getArgument('size');
47 47
 
48
-		if ($size) {
49
-			$parsedSize = Util::computerFileSize($size);
50
-			if ($parsedSize === false) {
51
-				$output->writeln('<error>Failed to parse input size</error>');
52
-				return -1;
53
-			}
54
-			if ($user) {
55
-				$this->config->setUserValue($user, 'files_trashbin', 'trashbin_size', (string)$parsedSize);
56
-				$this->commandBus->push(new Expire($user));
57
-			} else {
58
-				$this->config->setAppValue('files_trashbin', 'trashbin_size', (string)$parsedSize);
59
-				$output->writeln('<info>Warning: changing the default trashbin size will automatically trigger cleanup of existing trashbins,</info>');
60
-				$output->writeln('<info>a users trashbin can exceed the configured size until they move a new file to the trashbin.</info>');
61
-			}
62
-		} else {
63
-			$this->printTrashbinSize($input, $output, $user);
64
-		}
48
+        if ($size) {
49
+            $parsedSize = Util::computerFileSize($size);
50
+            if ($parsedSize === false) {
51
+                $output->writeln('<error>Failed to parse input size</error>');
52
+                return -1;
53
+            }
54
+            if ($user) {
55
+                $this->config->setUserValue($user, 'files_trashbin', 'trashbin_size', (string)$parsedSize);
56
+                $this->commandBus->push(new Expire($user));
57
+            } else {
58
+                $this->config->setAppValue('files_trashbin', 'trashbin_size', (string)$parsedSize);
59
+                $output->writeln('<info>Warning: changing the default trashbin size will automatically trigger cleanup of existing trashbins,</info>');
60
+                $output->writeln('<info>a users trashbin can exceed the configured size until they move a new file to the trashbin.</info>');
61
+            }
62
+        } else {
63
+            $this->printTrashbinSize($input, $output, $user);
64
+        }
65 65
 
66
-		return 0;
67
-	}
66
+        return 0;
67
+    }
68 68
 
69
-	private function printTrashbinSize(InputInterface $input, OutputInterface $output, ?string $user) {
70
-		$globalSize = (int)$this->config->getAppValue('files_trashbin', 'trashbin_size', '-1');
71
-		if ($globalSize < 0) {
72
-			$globalHumanSize = 'default (50% of available space)';
73
-		} else {
74
-			$globalHumanSize = Util::humanFileSize($globalSize);
75
-		}
69
+    private function printTrashbinSize(InputInterface $input, OutputInterface $output, ?string $user) {
70
+        $globalSize = (int)$this->config->getAppValue('files_trashbin', 'trashbin_size', '-1');
71
+        if ($globalSize < 0) {
72
+            $globalHumanSize = 'default (50% of available space)';
73
+        } else {
74
+            $globalHumanSize = Util::humanFileSize($globalSize);
75
+        }
76 76
 
77
-		if ($user) {
78
-			$userSize = (int)$this->config->getUserValue($user, 'files_trashbin', 'trashbin_size', '-1');
77
+        if ($user) {
78
+            $userSize = (int)$this->config->getUserValue($user, 'files_trashbin', 'trashbin_size', '-1');
79 79
 
80
-			if ($userSize < 0) {
81
-				$userHumanSize = ($globalSize < 0) ? $globalHumanSize : "default($globalHumanSize)";
82
-			} else {
83
-				$userHumanSize = Util::humanFileSize($userSize);
84
-			}
80
+            if ($userSize < 0) {
81
+                $userHumanSize = ($globalSize < 0) ? $globalHumanSize : "default($globalHumanSize)";
82
+            } else {
83
+                $userHumanSize = Util::humanFileSize($userSize);
84
+            }
85 85
 
86
-			if ($input->getOption('output') == self::OUTPUT_FORMAT_PLAIN) {
87
-				$output->writeln($userHumanSize);
88
-			} else {
89
-				$userValue = ($userSize < 0) ? 'default' : $userSize;
90
-				$globalValue = ($globalSize < 0) ? 'default' : $globalSize;
91
-				$this->writeArrayInOutputFormat($input, $output, [
92
-					'user_size' => $userValue,
93
-					'global_size' => $globalValue,
94
-					'effective_size' => ($userSize < 0) ? $globalValue : $userValue,
95
-				]);
96
-			}
97
-		} else {
98
-			$users = [];
99
-			$this->userManager->callForSeenUsers(function (IUser $user) use (&$users): void {
100
-				$users[] = $user->getUID();
101
-			});
102
-			$userValues = $this->config->getUserValueForUsers('files_trashbin', 'trashbin_size', $users);
86
+            if ($input->getOption('output') == self::OUTPUT_FORMAT_PLAIN) {
87
+                $output->writeln($userHumanSize);
88
+            } else {
89
+                $userValue = ($userSize < 0) ? 'default' : $userSize;
90
+                $globalValue = ($globalSize < 0) ? 'default' : $globalSize;
91
+                $this->writeArrayInOutputFormat($input, $output, [
92
+                    'user_size' => $userValue,
93
+                    'global_size' => $globalValue,
94
+                    'effective_size' => ($userSize < 0) ? $globalValue : $userValue,
95
+                ]);
96
+            }
97
+        } else {
98
+            $users = [];
99
+            $this->userManager->callForSeenUsers(function (IUser $user) use (&$users): void {
100
+                $users[] = $user->getUID();
101
+            });
102
+            $userValues = $this->config->getUserValueForUsers('files_trashbin', 'trashbin_size', $users);
103 103
 
104
-			if ($input->getOption('output') == self::OUTPUT_FORMAT_PLAIN) {
105
-				$output->writeln("Default size: $globalHumanSize");
106
-				$output->writeln('');
107
-				if (count($userValues)) {
108
-					$output->writeln('Per-user sizes:');
109
-					$this->writeArrayInOutputFormat($input, $output, array_map(function ($size) {
110
-						return Util::humanFileSize($size);
111
-					}, $userValues));
112
-				} else {
113
-					$output->writeln('No per-user sizes configured');
114
-				}
115
-			} else {
116
-				$globalValue = ($globalSize < 0) ? 'default' : $globalSize;
117
-				$this->writeArrayInOutputFormat($input, $output, [
118
-					'global_size' => $globalValue,
119
-					'user_sizes' => $userValues,
120
-				]);
121
-			}
122
-		}
123
-	}
104
+            if ($input->getOption('output') == self::OUTPUT_FORMAT_PLAIN) {
105
+                $output->writeln("Default size: $globalHumanSize");
106
+                $output->writeln('');
107
+                if (count($userValues)) {
108
+                    $output->writeln('Per-user sizes:');
109
+                    $this->writeArrayInOutputFormat($input, $output, array_map(function ($size) {
110
+                        return Util::humanFileSize($size);
111
+                    }, $userValues));
112
+                } else {
113
+                    $output->writeln('No per-user sizes configured');
114
+                }
115
+            } else {
116
+                $globalValue = ($globalSize < 0) ? 'default' : $globalSize;
117
+                $this->writeArrayInOutputFormat($input, $output, [
118
+                    'global_size' => $globalValue,
119
+                    'user_sizes' => $userValues,
120
+                ]);
121
+            }
122
+        }
123
+    }
124 124
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -52,10 +52,10 @@  discard block
 block discarded – undo
52 52
 				return -1;
53 53
 			}
54 54
 			if ($user) {
55
-				$this->config->setUserValue($user, 'files_trashbin', 'trashbin_size', (string)$parsedSize);
55
+				$this->config->setUserValue($user, 'files_trashbin', 'trashbin_size', (string) $parsedSize);
56 56
 				$this->commandBus->push(new Expire($user));
57 57
 			} else {
58
-				$this->config->setAppValue('files_trashbin', 'trashbin_size', (string)$parsedSize);
58
+				$this->config->setAppValue('files_trashbin', 'trashbin_size', (string) $parsedSize);
59 59
 				$output->writeln('<info>Warning: changing the default trashbin size will automatically trigger cleanup of existing trashbins,</info>');
60 60
 				$output->writeln('<info>a users trashbin can exceed the configured size until they move a new file to the trashbin.</info>');
61 61
 			}
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
 	}
68 68
 
69 69
 	private function printTrashbinSize(InputInterface $input, OutputInterface $output, ?string $user) {
70
-		$globalSize = (int)$this->config->getAppValue('files_trashbin', 'trashbin_size', '-1');
70
+		$globalSize = (int) $this->config->getAppValue('files_trashbin', 'trashbin_size', '-1');
71 71
 		if ($globalSize < 0) {
72 72
 			$globalHumanSize = 'default (50% of available space)';
73 73
 		} else {
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
 		}
76 76
 
77 77
 		if ($user) {
78
-			$userSize = (int)$this->config->getUserValue($user, 'files_trashbin', 'trashbin_size', '-1');
78
+			$userSize = (int) $this->config->getUserValue($user, 'files_trashbin', 'trashbin_size', '-1');
79 79
 
80 80
 			if ($userSize < 0) {
81 81
 				$userHumanSize = ($globalSize < 0) ? $globalHumanSize : "default($globalHumanSize)";
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 			}
97 97
 		} else {
98 98
 			$users = [];
99
-			$this->userManager->callForSeenUsers(function (IUser $user) use (&$users): void {
99
+			$this->userManager->callForSeenUsers(function(IUser $user) use (&$users): void {
100 100
 				$users[] = $user->getUID();
101 101
 			});
102 102
 			$userValues = $this->config->getUserValueForUsers('files_trashbin', 'trashbin_size', $users);
@@ -106,7 +106,7 @@  discard block
 block discarded – undo
106 106
 				$output->writeln('');
107 107
 				if (count($userValues)) {
108 108
 					$output->writeln('Per-user sizes:');
109
-					$this->writeArrayInOutputFormat($input, $output, array_map(function ($size) {
109
+					$this->writeArrayInOutputFormat($input, $output, array_map(function($size) {
110 110
 						return Util::humanFileSize($size);
111 111
 					}, $userValues));
112 112
 				} else {
Please login to merge, or discard this patch.
apps/files_trashbin/tests/TrashbinTest.php 1 patch
Indentation   +661 added lines, -661 removed lines patch added patch discarded remove patch
@@ -34,681 +34,681 @@
 block discarded – undo
34 34
  * @group DB
35 35
  */
36 36
 class TrashbinTest extends \Test\TestCase {
37
-	public const TEST_TRASHBIN_USER1 = 'test-trashbin-user1';
38
-	public const TEST_TRASHBIN_USER2 = 'test-trashbin-user2';
39
-
40
-	private $trashRoot1;
41
-	private $trashRoot2;
42
-
43
-	private static $rememberRetentionObligation;
44
-
45
-	/**
46
-	 * @var bool
47
-	 */
48
-	private static $trashBinStatus;
49
-
50
-	/**
51
-	 * @var View
52
-	 */
53
-	private $rootView;
54
-
55
-	public static function setUpBeforeClass(): void {
56
-		parent::setUpBeforeClass();
57
-
58
-		$appManager = Server::get(IAppManager::class);
59
-		self::$trashBinStatus = $appManager->isEnabledForUser('files_trashbin');
60
-
61
-		// reset backend
62
-		Server::get(IUserManager::class)->clearBackends();
63
-		Server::get(IUserManager::class)->registerBackend(new Database());
64
-
65
-		// clear share hooks
66
-		\OC_Hook::clear('OCP\\Share');
67
-		\OC::registerShareHooks(Server::get(SystemConfig::class));
68
-
69
-		// init files sharing
70
-		new Application();
71
-
72
-		//disable encryption
73
-		Server::get(IAppManager::class)->disableApp('encryption');
74
-
75
-		$config = Server::get(IConfig::class);
76
-		//configure trashbin
77
-		self::$rememberRetentionObligation = $config->getSystemValue('trashbin_retention_obligation', Expiration::DEFAULT_RETENTION_OBLIGATION);
78
-		/** @var Expiration $expiration */
79
-		$expiration = Server::get(Expiration::class);
80
-		$expiration->setRetentionObligation('auto, 2');
81
-
82
-		// register trashbin hooks
83
-		$trashbinApp = new TrashbinApplication();
84
-		$trashbinApp->boot(new BootContext(new DIContainer('', [], \OC::$server)));
85
-
86
-		// create test user
87
-		self::loginHelper(self::TEST_TRASHBIN_USER2, true);
88
-		self::loginHelper(self::TEST_TRASHBIN_USER1, true);
89
-	}
90
-
91
-
92
-	public static function tearDownAfterClass(): void {
93
-		// cleanup test user
94
-		$user = Server::get(IUserManager::class)->get(self::TEST_TRASHBIN_USER1);
95
-		if ($user !== null) {
96
-			$user->delete();
97
-		}
98
-
99
-		/** @var Expiration $expiration */
100
-		$expiration = Server::get(Expiration::class);
101
-		$expiration->setRetentionObligation(self::$rememberRetentionObligation);
102
-
103
-		\OC_Hook::clear();
104
-
105
-		Filesystem::getLoader()->removeStorageWrapper('oc_trashbin');
106
-
107
-		if (self::$trashBinStatus) {
108
-			Server::get(IAppManager::class)->enableApp('files_trashbin');
109
-		}
110
-
111
-		parent::tearDownAfterClass();
112
-	}
113
-
114
-	protected function setUp(): void {
115
-		parent::setUp();
116
-
117
-		Server::get(IAppManager::class)->enableApp('files_trashbin');
118
-		$config = Server::get(IConfig::class);
119
-		$mockConfig = $this->createMock(IConfig::class);
120
-		$mockConfig
121
-			->method('getSystemValue')
122
-			->willReturnCallback(static function ($key, $default) use ($config) {
123
-				if ($key === 'filesystem_check_changes') {
124
-					return Watcher::CHECK_ONCE;
125
-				} else {
126
-					return $config->getSystemValue($key, $default);
127
-				}
128
-			});
129
-		$mockConfig
130
-			->method('getUserValue')
131
-			->willReturnCallback(static function ($userId, $appName, $key, $default = '') use ($config) {
132
-				return $config->getUserValue($userId, $appName, $key, $default);
133
-			});
134
-		$mockConfig
135
-			->method('getAppValue')
136
-			->willReturnCallback(static function ($appName, $key, $default = '') use ($config) {
137
-				return $config->getAppValue($appName, $key, $default);
138
-			});
139
-		$this->overwriteService(AllConfig::class, $mockConfig);
140
-
141
-		$this->trashRoot1 = '/' . self::TEST_TRASHBIN_USER1 . '/files_trashbin';
142
-		$this->trashRoot2 = '/' . self::TEST_TRASHBIN_USER2 . '/files_trashbin';
143
-		$this->rootView = new View();
144
-		self::loginHelper(self::TEST_TRASHBIN_USER1);
145
-	}
146
-
147
-	protected function tearDown(): void {
148
-		$this->restoreService(AllConfig::class);
149
-		// disable trashbin to be able to properly clean up
150
-		Server::get(IAppManager::class)->disableApp('files_trashbin');
151
-
152
-		$this->rootView->deleteAll('/' . self::TEST_TRASHBIN_USER1 . '/files');
153
-		$this->rootView->deleteAll('/' . self::TEST_TRASHBIN_USER2 . '/files');
154
-		$this->rootView->deleteAll($this->trashRoot1);
155
-		$this->rootView->deleteAll($this->trashRoot2);
156
-
157
-		// clear trash table
158
-		$connection = Server::get(IDBConnection::class);
159
-		$connection->executeUpdate('DELETE FROM `*PREFIX*files_trash`');
160
-
161
-		parent::tearDown();
162
-	}
163
-
164
-	/**
165
-	 * test expiration of files older then the max storage time defined for the trash
166
-	 */
167
-	public function testExpireOldFiles(): void {
168
-
169
-		/** @var ITimeFactory $time */
170
-		$time = Server::get(ITimeFactory::class);
171
-		$currentTime = $time->getTime();
172
-		$expireAt = $currentTime - 2 * 24 * 60 * 60;
173
-		$expiredDate = $currentTime - 3 * 24 * 60 * 60;
174
-
175
-		// create some files
176
-		Filesystem::file_put_contents('file1.txt', 'file1');
177
-		Filesystem::file_put_contents('file2.txt', 'file2');
178
-		Filesystem::file_put_contents('file3.txt', 'file3');
179
-
180
-		// delete them so that they end up in the trash bin
181
-		Filesystem::unlink('file1.txt');
182
-		Filesystem::unlink('file2.txt');
183
-		Filesystem::unlink('file3.txt');
184
-
185
-		//make sure that files are in the trash bin
186
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'name');
187
-		$this->assertSame(3, count($filesInTrash));
188
-
189
-		// every second file will get a date in the past so that it will get expired
190
-		$manipulatedList = $this->manipulateDeleteTime($filesInTrash, $this->trashRoot1, $expiredDate);
191
-
192
-		$testClass = new TrashbinForTesting();
193
-		[$sizeOfDeletedFiles, $count] = $testClass->dummyDeleteExpiredFiles($manipulatedList, $expireAt);
194
-
195
-		$this->assertSame(10, $sizeOfDeletedFiles);
196
-		$this->assertSame(2, $count);
197
-
198
-		// only file2.txt should be left
199
-		$remainingFiles = array_slice($manipulatedList, $count);
200
-		$this->assertSame(1, count($remainingFiles));
201
-		$remainingFile = reset($remainingFiles);
202
-		// TODO: failing test
203
-		#$this->assertSame('file2.txt', $remainingFile['name']);
204
-
205
-		// check that file1.txt and file3.txt was really deleted
206
-		$newTrashContent = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
207
-		$this->assertSame(1, count($newTrashContent));
208
-		$element = reset($newTrashContent);
209
-		// TODO: failing test
210
-		#$this->assertSame('file2.txt', $element['name']);
211
-	}
212
-
213
-	/**
214
-	 * test expiration of files older then the max storage time defined for the trash
215
-	 * in this test we delete a shared file and check if both trash bins, the one from
216
-	 * the owner of the file and the one from the user who deleted the file get expired
217
-	 * correctly
218
-	 */
219
-	public function testExpireOldFilesShared(): void {
220
-		$currentTime = time();
221
-		$folder = 'trashTest-' . $currentTime . '/';
222
-		$expiredDate = $currentTime - 3 * 24 * 60 * 60;
223
-
224
-		// create some files
225
-		Filesystem::mkdir($folder);
226
-		Filesystem::file_put_contents($folder . 'user1-1.txt', 'file1');
227
-		Filesystem::file_put_contents($folder . 'user1-2.txt', 'file2');
228
-		Filesystem::file_put_contents($folder . 'user1-3.txt', 'file3');
229
-		Filesystem::file_put_contents($folder . 'user1-4.txt', 'file4');
230
-
231
-		//share user1-4.txt with user2
232
-		$node = \OC::$server->getUserFolder(self::TEST_TRASHBIN_USER1)->get($folder);
233
-		$share = Server::get(\OCP\Share\IManager::class)->newShare();
234
-		$share->setShareType(IShare::TYPE_USER)
235
-			->setNode($node)
236
-			->setSharedBy(self::TEST_TRASHBIN_USER1)
237
-			->setSharedWith(self::TEST_TRASHBIN_USER2)
238
-			->setPermissions(Constants::PERMISSION_ALL);
239
-		$share = Server::get(\OCP\Share\IManager::class)->createShare($share);
240
-		Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_TRASHBIN_USER2);
241
-
242
-		// delete them so that they end up in the trash bin
243
-		Filesystem::unlink($folder . 'user1-1.txt');
244
-		Filesystem::unlink($folder . 'user1-2.txt');
245
-		Filesystem::unlink($folder . 'user1-3.txt');
246
-
247
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'name');
248
-		$this->assertSame(3, count($filesInTrash));
249
-
250
-		// every second file will get a date in the past so that it will get expired
251
-		$this->manipulateDeleteTime($filesInTrash, $this->trashRoot1, $expiredDate);
252
-
253
-		// login as user2
254
-		self::loginHelper(self::TEST_TRASHBIN_USER2);
255
-
256
-		$this->assertTrue(Filesystem::file_exists($folder . 'user1-4.txt'));
257
-
258
-		// create some files
259
-		Filesystem::file_put_contents('user2-1.txt', 'file1');
260
-		Filesystem::file_put_contents('user2-2.txt', 'file2');
261
-
262
-		// delete them so that they end up in the trash bin
263
-		Filesystem::unlink('user2-1.txt');
264
-		Filesystem::unlink('user2-2.txt');
265
-
266
-		$filesInTrashUser2 = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2, 'name');
267
-		$this->assertSame(2, count($filesInTrashUser2));
268
-
269
-		// every second file will get a date in the past so that it will get expired
270
-		$this->manipulateDeleteTime($filesInTrashUser2, $this->trashRoot2, $expiredDate);
271
-
272
-		Filesystem::unlink($folder . 'user1-4.txt');
273
-
274
-		$this->runCommands();
275
-
276
-		$filesInTrashUser2AfterDelete = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2);
277
-
278
-		// user2-1.txt should have been expired
279
-		$this->verifyArray($filesInTrashUser2AfterDelete, ['user2-2.txt', 'user1-4.txt']);
280
-
281
-		self::loginHelper(self::TEST_TRASHBIN_USER1);
282
-
283
-		// user1-1.txt and user1-3.txt should have been expired
284
-		$filesInTrashUser1AfterDelete = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
285
-
286
-		$this->verifyArray($filesInTrashUser1AfterDelete, ['user1-2.txt', 'user1-4.txt']);
287
-	}
288
-
289
-	/**
290
-	 * verify that the array contains the expected results
291
-	 *
292
-	 * @param FileInfo[] $result
293
-	 * @param string[] $expected
294
-	 */
295
-	private function verifyArray($result, $expected) {
296
-		$this->assertSame(count($expected), count($result));
297
-		foreach ($expected as $expectedFile) {
298
-			$found = false;
299
-			foreach ($result as $fileInTrash) {
300
-				if ($expectedFile === $fileInTrash['name']) {
301
-					$found = true;
302
-					break;
303
-				}
304
-			}
305
-			if (!$found) {
306
-				// if we didn't found the expected file, something went wrong
307
-				$this->assertTrue(false, "can't find expected file '" . $expectedFile . "' in trash bin");
308
-			}
309
-		}
310
-	}
311
-
312
-	/**
313
-	 * @param FileInfo[] $files
314
-	 * @param string $trashRoot
315
-	 * @param integer $expireDate
316
-	 */
317
-	private function manipulateDeleteTime($files, $trashRoot, $expireDate) {
318
-		$counter = 0;
319
-		foreach ($files as &$file) {
320
-			// modify every second file
321
-			$counter = ($counter + 1) % 2;
322
-			if ($counter === 1) {
323
-				$source = $trashRoot . '/files/' . $file['name'] . '.d' . $file['mtime'];
324
-				$target = Filesystem::normalizePath($trashRoot . '/files/' . $file['name'] . '.d' . $expireDate);
325
-				$this->rootView->rename($source, $target);
326
-				$file['mtime'] = $expireDate;
327
-			}
328
-		}
329
-		return \OCA\Files\Helper::sortFiles($files, 'mtime');
330
-	}
331
-
332
-
333
-	/**
334
-	 * test expiration of old files in the trash bin until the max size
335
-	 * of the trash bin is met again
336
-	 */
337
-	public function testExpireOldFilesUtilLimitsAreMet(): void {
338
-
339
-		// create some files
340
-		Filesystem::file_put_contents('file1.txt', 'file1');
341
-		Filesystem::file_put_contents('file2.txt', 'file2');
342
-		Filesystem::file_put_contents('file3.txt', 'file3');
343
-
344
-		// delete them so that they end up in the trash bin
345
-		Filesystem::unlink('file3.txt');
346
-		sleep(1); // make sure that every file has a unique mtime
347
-		Filesystem::unlink('file2.txt');
348
-		sleep(1); // make sure that every file has a unique mtime
349
-		Filesystem::unlink('file1.txt');
350
-
351
-		//make sure that files are in the trash bin
352
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
353
-		$this->assertSame(3, count($filesInTrash));
354
-
355
-		$testClass = new TrashbinForTesting();
356
-		$sizeOfDeletedFiles = $testClass->dummyDeleteFiles($filesInTrash, -8);
357
-
358
-		// the two oldest files (file3.txt and file2.txt) should be deleted
359
-		$this->assertSame(10, $sizeOfDeletedFiles);
360
-
361
-		$newTrashContent = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
362
-		$this->assertSame(1, count($newTrashContent));
363
-		$element = reset($newTrashContent);
364
-		$this->assertSame('file1.txt', $element['name']);
365
-	}
366
-
367
-	/**
368
-	 * Test restoring a file
369
-	 */
370
-	public function testRestoreFileInRoot(): void {
371
-		$userFolder = \OC::$server->getUserFolder();
372
-		$file = $userFolder->newFile('file1.txt');
373
-		$file->putContent('foo');
374
-
375
-		$this->assertTrue($userFolder->nodeExists('file1.txt'));
376
-
377
-		$file->delete();
378
-
379
-		$this->assertFalse($userFolder->nodeExists('file1.txt'));
380
-
381
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
382
-		$this->assertCount(1, $filesInTrash);
383
-
384
-		/** @var FileInfo */
385
-		$trashedFile = $filesInTrash[0];
386
-
387
-		$this->assertTrue(
388
-			Trashbin::restore(
389
-				'file1.txt.d' . $trashedFile->getMtime(),
390
-				$trashedFile->getName(),
391
-				$trashedFile->getMtime()
392
-			)
393
-		);
394
-
395
-		$file = $userFolder->get('file1.txt');
396
-		$this->assertEquals('foo', $file->getContent());
397
-	}
398
-
399
-	/**
400
-	 * Test restoring a file in subfolder
401
-	 */
402
-	public function testRestoreFileInSubfolder(): void {
403
-		$userFolder = \OC::$server->getUserFolder();
404
-		$folder = $userFolder->newFolder('folder');
405
-		$file = $folder->newFile('file1.txt');
406
-		$file->putContent('foo');
407
-
408
-		$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
409
-
410
-		$file->delete();
411
-
412
-		$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
413
-
414
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
415
-		$this->assertCount(1, $filesInTrash);
416
-
417
-		/** @var FileInfo */
418
-		$trashedFile = $filesInTrash[0];
419
-
420
-		$this->assertTrue(
421
-			Trashbin::restore(
422
-				'file1.txt.d' . $trashedFile->getMtime(),
423
-				$trashedFile->getName(),
424
-				$trashedFile->getMtime()
425
-			)
426
-		);
427
-
428
-		$file = $userFolder->get('folder/file1.txt');
429
-		$this->assertEquals('foo', $file->getContent());
430
-	}
431
-
432
-	/**
433
-	 * Test restoring a folder
434
-	 */
435
-	public function testRestoreFolder(): void {
436
-		$userFolder = \OC::$server->getUserFolder();
437
-		$folder = $userFolder->newFolder('folder');
438
-		$file = $folder->newFile('file1.txt');
439
-		$file->putContent('foo');
440
-
441
-		$this->assertTrue($userFolder->nodeExists('folder'));
442
-
443
-		$folder->delete();
444
-
445
-		$this->assertFalse($userFolder->nodeExists('folder'));
446
-
447
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
448
-		$this->assertCount(1, $filesInTrash);
37
+    public const TEST_TRASHBIN_USER1 = 'test-trashbin-user1';
38
+    public const TEST_TRASHBIN_USER2 = 'test-trashbin-user2';
39
+
40
+    private $trashRoot1;
41
+    private $trashRoot2;
42
+
43
+    private static $rememberRetentionObligation;
44
+
45
+    /**
46
+     * @var bool
47
+     */
48
+    private static $trashBinStatus;
49
+
50
+    /**
51
+     * @var View
52
+     */
53
+    private $rootView;
54
+
55
+    public static function setUpBeforeClass(): void {
56
+        parent::setUpBeforeClass();
57
+
58
+        $appManager = Server::get(IAppManager::class);
59
+        self::$trashBinStatus = $appManager->isEnabledForUser('files_trashbin');
60
+
61
+        // reset backend
62
+        Server::get(IUserManager::class)->clearBackends();
63
+        Server::get(IUserManager::class)->registerBackend(new Database());
64
+
65
+        // clear share hooks
66
+        \OC_Hook::clear('OCP\\Share');
67
+        \OC::registerShareHooks(Server::get(SystemConfig::class));
68
+
69
+        // init files sharing
70
+        new Application();
71
+
72
+        //disable encryption
73
+        Server::get(IAppManager::class)->disableApp('encryption');
74
+
75
+        $config = Server::get(IConfig::class);
76
+        //configure trashbin
77
+        self::$rememberRetentionObligation = $config->getSystemValue('trashbin_retention_obligation', Expiration::DEFAULT_RETENTION_OBLIGATION);
78
+        /** @var Expiration $expiration */
79
+        $expiration = Server::get(Expiration::class);
80
+        $expiration->setRetentionObligation('auto, 2');
81
+
82
+        // register trashbin hooks
83
+        $trashbinApp = new TrashbinApplication();
84
+        $trashbinApp->boot(new BootContext(new DIContainer('', [], \OC::$server)));
85
+
86
+        // create test user
87
+        self::loginHelper(self::TEST_TRASHBIN_USER2, true);
88
+        self::loginHelper(self::TEST_TRASHBIN_USER1, true);
89
+    }
90
+
91
+
92
+    public static function tearDownAfterClass(): void {
93
+        // cleanup test user
94
+        $user = Server::get(IUserManager::class)->get(self::TEST_TRASHBIN_USER1);
95
+        if ($user !== null) {
96
+            $user->delete();
97
+        }
98
+
99
+        /** @var Expiration $expiration */
100
+        $expiration = Server::get(Expiration::class);
101
+        $expiration->setRetentionObligation(self::$rememberRetentionObligation);
102
+
103
+        \OC_Hook::clear();
104
+
105
+        Filesystem::getLoader()->removeStorageWrapper('oc_trashbin');
106
+
107
+        if (self::$trashBinStatus) {
108
+            Server::get(IAppManager::class)->enableApp('files_trashbin');
109
+        }
110
+
111
+        parent::tearDownAfterClass();
112
+    }
113
+
114
+    protected function setUp(): void {
115
+        parent::setUp();
116
+
117
+        Server::get(IAppManager::class)->enableApp('files_trashbin');
118
+        $config = Server::get(IConfig::class);
119
+        $mockConfig = $this->createMock(IConfig::class);
120
+        $mockConfig
121
+            ->method('getSystemValue')
122
+            ->willReturnCallback(static function ($key, $default) use ($config) {
123
+                if ($key === 'filesystem_check_changes') {
124
+                    return Watcher::CHECK_ONCE;
125
+                } else {
126
+                    return $config->getSystemValue($key, $default);
127
+                }
128
+            });
129
+        $mockConfig
130
+            ->method('getUserValue')
131
+            ->willReturnCallback(static function ($userId, $appName, $key, $default = '') use ($config) {
132
+                return $config->getUserValue($userId, $appName, $key, $default);
133
+            });
134
+        $mockConfig
135
+            ->method('getAppValue')
136
+            ->willReturnCallback(static function ($appName, $key, $default = '') use ($config) {
137
+                return $config->getAppValue($appName, $key, $default);
138
+            });
139
+        $this->overwriteService(AllConfig::class, $mockConfig);
140
+
141
+        $this->trashRoot1 = '/' . self::TEST_TRASHBIN_USER1 . '/files_trashbin';
142
+        $this->trashRoot2 = '/' . self::TEST_TRASHBIN_USER2 . '/files_trashbin';
143
+        $this->rootView = new View();
144
+        self::loginHelper(self::TEST_TRASHBIN_USER1);
145
+    }
146
+
147
+    protected function tearDown(): void {
148
+        $this->restoreService(AllConfig::class);
149
+        // disable trashbin to be able to properly clean up
150
+        Server::get(IAppManager::class)->disableApp('files_trashbin');
151
+
152
+        $this->rootView->deleteAll('/' . self::TEST_TRASHBIN_USER1 . '/files');
153
+        $this->rootView->deleteAll('/' . self::TEST_TRASHBIN_USER2 . '/files');
154
+        $this->rootView->deleteAll($this->trashRoot1);
155
+        $this->rootView->deleteAll($this->trashRoot2);
156
+
157
+        // clear trash table
158
+        $connection = Server::get(IDBConnection::class);
159
+        $connection->executeUpdate('DELETE FROM `*PREFIX*files_trash`');
160
+
161
+        parent::tearDown();
162
+    }
163
+
164
+    /**
165
+     * test expiration of files older then the max storage time defined for the trash
166
+     */
167
+    public function testExpireOldFiles(): void {
168
+
169
+        /** @var ITimeFactory $time */
170
+        $time = Server::get(ITimeFactory::class);
171
+        $currentTime = $time->getTime();
172
+        $expireAt = $currentTime - 2 * 24 * 60 * 60;
173
+        $expiredDate = $currentTime - 3 * 24 * 60 * 60;
174
+
175
+        // create some files
176
+        Filesystem::file_put_contents('file1.txt', 'file1');
177
+        Filesystem::file_put_contents('file2.txt', 'file2');
178
+        Filesystem::file_put_contents('file3.txt', 'file3');
179
+
180
+        // delete them so that they end up in the trash bin
181
+        Filesystem::unlink('file1.txt');
182
+        Filesystem::unlink('file2.txt');
183
+        Filesystem::unlink('file3.txt');
184
+
185
+        //make sure that files are in the trash bin
186
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'name');
187
+        $this->assertSame(3, count($filesInTrash));
188
+
189
+        // every second file will get a date in the past so that it will get expired
190
+        $manipulatedList = $this->manipulateDeleteTime($filesInTrash, $this->trashRoot1, $expiredDate);
191
+
192
+        $testClass = new TrashbinForTesting();
193
+        [$sizeOfDeletedFiles, $count] = $testClass->dummyDeleteExpiredFiles($manipulatedList, $expireAt);
194
+
195
+        $this->assertSame(10, $sizeOfDeletedFiles);
196
+        $this->assertSame(2, $count);
197
+
198
+        // only file2.txt should be left
199
+        $remainingFiles = array_slice($manipulatedList, $count);
200
+        $this->assertSame(1, count($remainingFiles));
201
+        $remainingFile = reset($remainingFiles);
202
+        // TODO: failing test
203
+        #$this->assertSame('file2.txt', $remainingFile['name']);
204
+
205
+        // check that file1.txt and file3.txt was really deleted
206
+        $newTrashContent = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
207
+        $this->assertSame(1, count($newTrashContent));
208
+        $element = reset($newTrashContent);
209
+        // TODO: failing test
210
+        #$this->assertSame('file2.txt', $element['name']);
211
+    }
212
+
213
+    /**
214
+     * test expiration of files older then the max storage time defined for the trash
215
+     * in this test we delete a shared file and check if both trash bins, the one from
216
+     * the owner of the file and the one from the user who deleted the file get expired
217
+     * correctly
218
+     */
219
+    public function testExpireOldFilesShared(): void {
220
+        $currentTime = time();
221
+        $folder = 'trashTest-' . $currentTime . '/';
222
+        $expiredDate = $currentTime - 3 * 24 * 60 * 60;
223
+
224
+        // create some files
225
+        Filesystem::mkdir($folder);
226
+        Filesystem::file_put_contents($folder . 'user1-1.txt', 'file1');
227
+        Filesystem::file_put_contents($folder . 'user1-2.txt', 'file2');
228
+        Filesystem::file_put_contents($folder . 'user1-3.txt', 'file3');
229
+        Filesystem::file_put_contents($folder . 'user1-4.txt', 'file4');
230
+
231
+        //share user1-4.txt with user2
232
+        $node = \OC::$server->getUserFolder(self::TEST_TRASHBIN_USER1)->get($folder);
233
+        $share = Server::get(\OCP\Share\IManager::class)->newShare();
234
+        $share->setShareType(IShare::TYPE_USER)
235
+            ->setNode($node)
236
+            ->setSharedBy(self::TEST_TRASHBIN_USER1)
237
+            ->setSharedWith(self::TEST_TRASHBIN_USER2)
238
+            ->setPermissions(Constants::PERMISSION_ALL);
239
+        $share = Server::get(\OCP\Share\IManager::class)->createShare($share);
240
+        Server::get(\OCP\Share\IManager::class)->acceptShare($share, self::TEST_TRASHBIN_USER2);
241
+
242
+        // delete them so that they end up in the trash bin
243
+        Filesystem::unlink($folder . 'user1-1.txt');
244
+        Filesystem::unlink($folder . 'user1-2.txt');
245
+        Filesystem::unlink($folder . 'user1-3.txt');
246
+
247
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'name');
248
+        $this->assertSame(3, count($filesInTrash));
249
+
250
+        // every second file will get a date in the past so that it will get expired
251
+        $this->manipulateDeleteTime($filesInTrash, $this->trashRoot1, $expiredDate);
252
+
253
+        // login as user2
254
+        self::loginHelper(self::TEST_TRASHBIN_USER2);
255
+
256
+        $this->assertTrue(Filesystem::file_exists($folder . 'user1-4.txt'));
257
+
258
+        // create some files
259
+        Filesystem::file_put_contents('user2-1.txt', 'file1');
260
+        Filesystem::file_put_contents('user2-2.txt', 'file2');
261
+
262
+        // delete them so that they end up in the trash bin
263
+        Filesystem::unlink('user2-1.txt');
264
+        Filesystem::unlink('user2-2.txt');
265
+
266
+        $filesInTrashUser2 = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2, 'name');
267
+        $this->assertSame(2, count($filesInTrashUser2));
268
+
269
+        // every second file will get a date in the past so that it will get expired
270
+        $this->manipulateDeleteTime($filesInTrashUser2, $this->trashRoot2, $expiredDate);
271
+
272
+        Filesystem::unlink($folder . 'user1-4.txt');
273
+
274
+        $this->runCommands();
275
+
276
+        $filesInTrashUser2AfterDelete = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER2);
277
+
278
+        // user2-1.txt should have been expired
279
+        $this->verifyArray($filesInTrashUser2AfterDelete, ['user2-2.txt', 'user1-4.txt']);
280
+
281
+        self::loginHelper(self::TEST_TRASHBIN_USER1);
282
+
283
+        // user1-1.txt and user1-3.txt should have been expired
284
+        $filesInTrashUser1AfterDelete = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
285
+
286
+        $this->verifyArray($filesInTrashUser1AfterDelete, ['user1-2.txt', 'user1-4.txt']);
287
+    }
288
+
289
+    /**
290
+     * verify that the array contains the expected results
291
+     *
292
+     * @param FileInfo[] $result
293
+     * @param string[] $expected
294
+     */
295
+    private function verifyArray($result, $expected) {
296
+        $this->assertSame(count($expected), count($result));
297
+        foreach ($expected as $expectedFile) {
298
+            $found = false;
299
+            foreach ($result as $fileInTrash) {
300
+                if ($expectedFile === $fileInTrash['name']) {
301
+                    $found = true;
302
+                    break;
303
+                }
304
+            }
305
+            if (!$found) {
306
+                // if we didn't found the expected file, something went wrong
307
+                $this->assertTrue(false, "can't find expected file '" . $expectedFile . "' in trash bin");
308
+            }
309
+        }
310
+    }
311
+
312
+    /**
313
+     * @param FileInfo[] $files
314
+     * @param string $trashRoot
315
+     * @param integer $expireDate
316
+     */
317
+    private function manipulateDeleteTime($files, $trashRoot, $expireDate) {
318
+        $counter = 0;
319
+        foreach ($files as &$file) {
320
+            // modify every second file
321
+            $counter = ($counter + 1) % 2;
322
+            if ($counter === 1) {
323
+                $source = $trashRoot . '/files/' . $file['name'] . '.d' . $file['mtime'];
324
+                $target = Filesystem::normalizePath($trashRoot . '/files/' . $file['name'] . '.d' . $expireDate);
325
+                $this->rootView->rename($source, $target);
326
+                $file['mtime'] = $expireDate;
327
+            }
328
+        }
329
+        return \OCA\Files\Helper::sortFiles($files, 'mtime');
330
+    }
331
+
332
+
333
+    /**
334
+     * test expiration of old files in the trash bin until the max size
335
+     * of the trash bin is met again
336
+     */
337
+    public function testExpireOldFilesUtilLimitsAreMet(): void {
338
+
339
+        // create some files
340
+        Filesystem::file_put_contents('file1.txt', 'file1');
341
+        Filesystem::file_put_contents('file2.txt', 'file2');
342
+        Filesystem::file_put_contents('file3.txt', 'file3');
343
+
344
+        // delete them so that they end up in the trash bin
345
+        Filesystem::unlink('file3.txt');
346
+        sleep(1); // make sure that every file has a unique mtime
347
+        Filesystem::unlink('file2.txt');
348
+        sleep(1); // make sure that every file has a unique mtime
349
+        Filesystem::unlink('file1.txt');
350
+
351
+        //make sure that files are in the trash bin
352
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
353
+        $this->assertSame(3, count($filesInTrash));
354
+
355
+        $testClass = new TrashbinForTesting();
356
+        $sizeOfDeletedFiles = $testClass->dummyDeleteFiles($filesInTrash, -8);
357
+
358
+        // the two oldest files (file3.txt and file2.txt) should be deleted
359
+        $this->assertSame(10, $sizeOfDeletedFiles);
360
+
361
+        $newTrashContent = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1);
362
+        $this->assertSame(1, count($newTrashContent));
363
+        $element = reset($newTrashContent);
364
+        $this->assertSame('file1.txt', $element['name']);
365
+    }
366
+
367
+    /**
368
+     * Test restoring a file
369
+     */
370
+    public function testRestoreFileInRoot(): void {
371
+        $userFolder = \OC::$server->getUserFolder();
372
+        $file = $userFolder->newFile('file1.txt');
373
+        $file->putContent('foo');
374
+
375
+        $this->assertTrue($userFolder->nodeExists('file1.txt'));
376
+
377
+        $file->delete();
378
+
379
+        $this->assertFalse($userFolder->nodeExists('file1.txt'));
380
+
381
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
382
+        $this->assertCount(1, $filesInTrash);
383
+
384
+        /** @var FileInfo */
385
+        $trashedFile = $filesInTrash[0];
386
+
387
+        $this->assertTrue(
388
+            Trashbin::restore(
389
+                'file1.txt.d' . $trashedFile->getMtime(),
390
+                $trashedFile->getName(),
391
+                $trashedFile->getMtime()
392
+            )
393
+        );
394
+
395
+        $file = $userFolder->get('file1.txt');
396
+        $this->assertEquals('foo', $file->getContent());
397
+    }
398
+
399
+    /**
400
+     * Test restoring a file in subfolder
401
+     */
402
+    public function testRestoreFileInSubfolder(): void {
403
+        $userFolder = \OC::$server->getUserFolder();
404
+        $folder = $userFolder->newFolder('folder');
405
+        $file = $folder->newFile('file1.txt');
406
+        $file->putContent('foo');
407
+
408
+        $this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
409
+
410
+        $file->delete();
411
+
412
+        $this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
413
+
414
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
415
+        $this->assertCount(1, $filesInTrash);
416
+
417
+        /** @var FileInfo */
418
+        $trashedFile = $filesInTrash[0];
419
+
420
+        $this->assertTrue(
421
+            Trashbin::restore(
422
+                'file1.txt.d' . $trashedFile->getMtime(),
423
+                $trashedFile->getName(),
424
+                $trashedFile->getMtime()
425
+            )
426
+        );
427
+
428
+        $file = $userFolder->get('folder/file1.txt');
429
+        $this->assertEquals('foo', $file->getContent());
430
+    }
431
+
432
+    /**
433
+     * Test restoring a folder
434
+     */
435
+    public function testRestoreFolder(): void {
436
+        $userFolder = \OC::$server->getUserFolder();
437
+        $folder = $userFolder->newFolder('folder');
438
+        $file = $folder->newFile('file1.txt');
439
+        $file->putContent('foo');
440
+
441
+        $this->assertTrue($userFolder->nodeExists('folder'));
442
+
443
+        $folder->delete();
444
+
445
+        $this->assertFalse($userFolder->nodeExists('folder'));
446
+
447
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
448
+        $this->assertCount(1, $filesInTrash);
449 449
 
450
-		/** @var FileInfo */
451
-		$trashedFolder = $filesInTrash[0];
450
+        /** @var FileInfo */
451
+        $trashedFolder = $filesInTrash[0];
452 452
 
453
-		$this->assertTrue(
454
-			Trashbin::restore(
455
-				'folder.d' . $trashedFolder->getMtime(),
456
-				$trashedFolder->getName(),
457
-				$trashedFolder->getMtime()
458
-			)
459
-		);
453
+        $this->assertTrue(
454
+            Trashbin::restore(
455
+                'folder.d' . $trashedFolder->getMtime(),
456
+                $trashedFolder->getName(),
457
+                $trashedFolder->getMtime()
458
+            )
459
+        );
460 460
 
461
-		$file = $userFolder->get('folder/file1.txt');
462
-		$this->assertEquals('foo', $file->getContent());
463
-	}
464
-
465
-	/**
466
-	 * Test restoring a file from inside a trashed folder
467
-	 */
468
-	public function testRestoreFileFromTrashedSubfolder(): void {
469
-		$userFolder = \OC::$server->getUserFolder();
470
-		$folder = $userFolder->newFolder('folder');
471
-		$file = $folder->newFile('file1.txt');
472
-		$file->putContent('foo');
461
+        $file = $userFolder->get('folder/file1.txt');
462
+        $this->assertEquals('foo', $file->getContent());
463
+    }
464
+
465
+    /**
466
+     * Test restoring a file from inside a trashed folder
467
+     */
468
+    public function testRestoreFileFromTrashedSubfolder(): void {
469
+        $userFolder = \OC::$server->getUserFolder();
470
+        $folder = $userFolder->newFolder('folder');
471
+        $file = $folder->newFile('file1.txt');
472
+        $file->putContent('foo');
473 473
 
474
-		$this->assertTrue($userFolder->nodeExists('folder'));
474
+        $this->assertTrue($userFolder->nodeExists('folder'));
475 475
 
476
-		$folder->delete();
477
-
478
-		$this->assertFalse($userFolder->nodeExists('folder'));
479
-
480
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
481
-		$this->assertCount(1, $filesInTrash);
482
-
483
-		/** @var FileInfo */
484
-		$trashedFile = $filesInTrash[0];
485
-
486
-		$this->assertTrue(
487
-			Trashbin::restore(
488
-				'folder.d' . $trashedFile->getMtime() . '/file1.txt',
489
-				'file1.txt',
490
-				$trashedFile->getMtime()
491
-			)
492
-		);
476
+        $folder->delete();
477
+
478
+        $this->assertFalse($userFolder->nodeExists('folder'));
479
+
480
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
481
+        $this->assertCount(1, $filesInTrash);
482
+
483
+        /** @var FileInfo */
484
+        $trashedFile = $filesInTrash[0];
485
+
486
+        $this->assertTrue(
487
+            Trashbin::restore(
488
+                'folder.d' . $trashedFile->getMtime() . '/file1.txt',
489
+                'file1.txt',
490
+                $trashedFile->getMtime()
491
+            )
492
+        );
493 493
 
494
-		$file = $userFolder->get('file1.txt');
495
-		$this->assertEquals('foo', $file->getContent());
496
-	}
494
+        $file = $userFolder->get('file1.txt');
495
+        $this->assertEquals('foo', $file->getContent());
496
+    }
497 497
 
498
-	/**
499
-	 * Test restoring a file whenever the source folder was removed.
500
-	 * The file should then land in the root.
501
-	 */
502
-	public function testRestoreFileWithMissingSourceFolder(): void {
503
-		$userFolder = \OC::$server->getUserFolder();
504
-		$folder = $userFolder->newFolder('folder');
505
-		$file = $folder->newFile('file1.txt');
506
-		$file->putContent('foo');
498
+    /**
499
+     * Test restoring a file whenever the source folder was removed.
500
+     * The file should then land in the root.
501
+     */
502
+    public function testRestoreFileWithMissingSourceFolder(): void {
503
+        $userFolder = \OC::$server->getUserFolder();
504
+        $folder = $userFolder->newFolder('folder');
505
+        $file = $folder->newFile('file1.txt');
506
+        $file->putContent('foo');
507 507
 
508
-		$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
508
+        $this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
509 509
 
510
-		$file->delete();
510
+        $file->delete();
511 511
 
512
-		$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
513
-
514
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
515
-		$this->assertCount(1, $filesInTrash);
516
-
517
-		/** @var FileInfo */
518
-		$trashedFile = $filesInTrash[0];
519
-
520
-		// delete source folder
521
-		$folder->delete();
522
-
523
-		$this->assertTrue(
524
-			Trashbin::restore(
525
-				'file1.txt.d' . $trashedFile->getMtime(),
526
-				$trashedFile->getName(),
527
-				$trashedFile->getMtime()
528
-			)
529
-		);
530
-
531
-		$file = $userFolder->get('file1.txt');
532
-		$this->assertEquals('foo', $file->getContent());
533
-	}
534
-
535
-	/**
536
-	 * Test restoring a file in the root folder whenever there is another file
537
-	 * with the same name in the root folder
538
-	 */
539
-	public function testRestoreFileDoesNotOverwriteExistingInRoot(): void {
540
-		$userFolder = \OC::$server->getUserFolder();
541
-		$file = $userFolder->newFile('file1.txt');
542
-		$file->putContent('foo');
543
-
544
-		$this->assertTrue($userFolder->nodeExists('file1.txt'));
545
-
546
-		$file->delete();
547
-
548
-		$this->assertFalse($userFolder->nodeExists('file1.txt'));
549
-
550
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
551
-		$this->assertCount(1, $filesInTrash);
552
-
553
-		/** @var FileInfo */
554
-		$trashedFile = $filesInTrash[0];
555
-
556
-		// create another file
557
-		$file = $userFolder->newFile('file1.txt');
558
-		$file->putContent('bar');
559
-
560
-		$this->assertTrue(
561
-			Trashbin::restore(
562
-				'file1.txt.d' . $trashedFile->getMtime(),
563
-				$trashedFile->getName(),
564
-				$trashedFile->getMtime()
565
-			)
566
-		);
567
-
568
-		$anotherFile = $userFolder->get('file1.txt');
569
-		$this->assertEquals('bar', $anotherFile->getContent());
570
-
571
-		$restoredFile = $userFolder->get('file1 (restored).txt');
572
-		$this->assertEquals('foo', $restoredFile->getContent());
573
-	}
574
-
575
-	/**
576
-	 * Test restoring a file whenever there is another file
577
-	 * with the same name in the source folder
578
-	 */
579
-	public function testRestoreFileDoesNotOverwriteExistingInSubfolder(): void {
580
-		$userFolder = \OC::$server->getUserFolder();
581
-		$folder = $userFolder->newFolder('folder');
582
-		$file = $folder->newFile('file1.txt');
583
-		$file->putContent('foo');
584
-
585
-		$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
586
-
587
-		$file->delete();
588
-
589
-		$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
590
-
591
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
592
-		$this->assertCount(1, $filesInTrash);
593
-
594
-		/** @var FileInfo */
595
-		$trashedFile = $filesInTrash[0];
596
-
597
-		// create another file
598
-		$file = $folder->newFile('file1.txt');
599
-		$file->putContent('bar');
600
-
601
-		$this->assertTrue(
602
-			Trashbin::restore(
603
-				'file1.txt.d' . $trashedFile->getMtime(),
604
-				$trashedFile->getName(),
605
-				$trashedFile->getMtime()
606
-			)
607
-		);
608
-
609
-		$anotherFile = $userFolder->get('folder/file1.txt');
610
-		$this->assertEquals('bar', $anotherFile->getContent());
611
-
612
-		$restoredFile = $userFolder->get('folder/file1 (restored).txt');
613
-		$this->assertEquals('foo', $restoredFile->getContent());
614
-	}
615
-
616
-	/**
617
-	 * Test restoring a non-existing file from trashbin, returns false
618
-	 */
619
-	public function testRestoreUnexistingFile(): void {
620
-		$this->assertFalse(
621
-			Trashbin::restore(
622
-				'unexist.txt.d123456',
623
-				'unexist.txt',
624
-				'123456'
625
-			)
626
-		);
627
-	}
628
-
629
-	/**
630
-	 * Test restoring a file into a read-only folder, will restore
631
-	 * the file to root instead
632
-	 */
633
-	public function testRestoreFileIntoReadOnlySourceFolder(): void {
634
-		$userFolder = \OC::$server->getUserFolder();
635
-		$folder = $userFolder->newFolder('folder');
636
-		$file = $folder->newFile('file1.txt');
637
-		$file->putContent('foo');
638
-
639
-		$this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
640
-
641
-		$file->delete();
642
-
643
-		$this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
644
-
645
-		$filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
646
-		$this->assertCount(1, $filesInTrash);
647
-
648
-		/** @var FileInfo */
649
-		$trashedFile = $filesInTrash[0];
650
-
651
-		// delete source folder
652
-		[$storage, $internalPath] = $this->rootView->resolvePath('/' . self::TEST_TRASHBIN_USER1 . '/files/folder');
653
-		if ($storage instanceof Local) {
654
-			$folderAbsPath = $storage->getSourcePath($internalPath);
655
-			// make folder read-only
656
-			chmod($folderAbsPath, 0555);
657
-
658
-			$this->assertTrue(
659
-				Trashbin::restore(
660
-					'file1.txt.d' . $trashedFile->getMtime(),
661
-					$trashedFile->getName(),
662
-					$trashedFile->getMtime()
663
-				)
664
-			);
665
-
666
-			$file = $userFolder->get('file1.txt');
667
-			$this->assertEquals('foo', $file->getContent());
668
-
669
-			chmod($folderAbsPath, 0755);
670
-		}
671
-	}
672
-
673
-	/**
674
-	 * @param string $user
675
-	 * @param bool $create
676
-	 */
677
-	public static function loginHelper($user, $create = false) {
678
-		if ($create) {
679
-			try {
680
-				Server::get(IUserManager::class)->createUser($user, $user);
681
-			} catch (\Exception $e) { // catch username is already being used from previous aborted runs
682
-			}
683
-		}
684
-
685
-		\OC_Util::tearDownFS();
686
-		\OC_User::setUserId('');
687
-		Filesystem::tearDown();
688
-		\OC_User::setUserId($user);
689
-		\OC_Util::setupFS($user);
690
-		\OC::$server->getUserFolder($user);
691
-	}
512
+        $this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
513
+
514
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
515
+        $this->assertCount(1, $filesInTrash);
516
+
517
+        /** @var FileInfo */
518
+        $trashedFile = $filesInTrash[0];
519
+
520
+        // delete source folder
521
+        $folder->delete();
522
+
523
+        $this->assertTrue(
524
+            Trashbin::restore(
525
+                'file1.txt.d' . $trashedFile->getMtime(),
526
+                $trashedFile->getName(),
527
+                $trashedFile->getMtime()
528
+            )
529
+        );
530
+
531
+        $file = $userFolder->get('file1.txt');
532
+        $this->assertEquals('foo', $file->getContent());
533
+    }
534
+
535
+    /**
536
+     * Test restoring a file in the root folder whenever there is another file
537
+     * with the same name in the root folder
538
+     */
539
+    public function testRestoreFileDoesNotOverwriteExistingInRoot(): void {
540
+        $userFolder = \OC::$server->getUserFolder();
541
+        $file = $userFolder->newFile('file1.txt');
542
+        $file->putContent('foo');
543
+
544
+        $this->assertTrue($userFolder->nodeExists('file1.txt'));
545
+
546
+        $file->delete();
547
+
548
+        $this->assertFalse($userFolder->nodeExists('file1.txt'));
549
+
550
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
551
+        $this->assertCount(1, $filesInTrash);
552
+
553
+        /** @var FileInfo */
554
+        $trashedFile = $filesInTrash[0];
555
+
556
+        // create another file
557
+        $file = $userFolder->newFile('file1.txt');
558
+        $file->putContent('bar');
559
+
560
+        $this->assertTrue(
561
+            Trashbin::restore(
562
+                'file1.txt.d' . $trashedFile->getMtime(),
563
+                $trashedFile->getName(),
564
+                $trashedFile->getMtime()
565
+            )
566
+        );
567
+
568
+        $anotherFile = $userFolder->get('file1.txt');
569
+        $this->assertEquals('bar', $anotherFile->getContent());
570
+
571
+        $restoredFile = $userFolder->get('file1 (restored).txt');
572
+        $this->assertEquals('foo', $restoredFile->getContent());
573
+    }
574
+
575
+    /**
576
+     * Test restoring a file whenever there is another file
577
+     * with the same name in the source folder
578
+     */
579
+    public function testRestoreFileDoesNotOverwriteExistingInSubfolder(): void {
580
+        $userFolder = \OC::$server->getUserFolder();
581
+        $folder = $userFolder->newFolder('folder');
582
+        $file = $folder->newFile('file1.txt');
583
+        $file->putContent('foo');
584
+
585
+        $this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
586
+
587
+        $file->delete();
588
+
589
+        $this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
590
+
591
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
592
+        $this->assertCount(1, $filesInTrash);
593
+
594
+        /** @var FileInfo */
595
+        $trashedFile = $filesInTrash[0];
596
+
597
+        // create another file
598
+        $file = $folder->newFile('file1.txt');
599
+        $file->putContent('bar');
600
+
601
+        $this->assertTrue(
602
+            Trashbin::restore(
603
+                'file1.txt.d' . $trashedFile->getMtime(),
604
+                $trashedFile->getName(),
605
+                $trashedFile->getMtime()
606
+            )
607
+        );
608
+
609
+        $anotherFile = $userFolder->get('folder/file1.txt');
610
+        $this->assertEquals('bar', $anotherFile->getContent());
611
+
612
+        $restoredFile = $userFolder->get('folder/file1 (restored).txt');
613
+        $this->assertEquals('foo', $restoredFile->getContent());
614
+    }
615
+
616
+    /**
617
+     * Test restoring a non-existing file from trashbin, returns false
618
+     */
619
+    public function testRestoreUnexistingFile(): void {
620
+        $this->assertFalse(
621
+            Trashbin::restore(
622
+                'unexist.txt.d123456',
623
+                'unexist.txt',
624
+                '123456'
625
+            )
626
+        );
627
+    }
628
+
629
+    /**
630
+     * Test restoring a file into a read-only folder, will restore
631
+     * the file to root instead
632
+     */
633
+    public function testRestoreFileIntoReadOnlySourceFolder(): void {
634
+        $userFolder = \OC::$server->getUserFolder();
635
+        $folder = $userFolder->newFolder('folder');
636
+        $file = $folder->newFile('file1.txt');
637
+        $file->putContent('foo');
638
+
639
+        $this->assertTrue($userFolder->nodeExists('folder/file1.txt'));
640
+
641
+        $file->delete();
642
+
643
+        $this->assertFalse($userFolder->nodeExists('folder/file1.txt'));
644
+
645
+        $filesInTrash = Helper::getTrashFiles('/', self::TEST_TRASHBIN_USER1, 'mtime');
646
+        $this->assertCount(1, $filesInTrash);
647
+
648
+        /** @var FileInfo */
649
+        $trashedFile = $filesInTrash[0];
650
+
651
+        // delete source folder
652
+        [$storage, $internalPath] = $this->rootView->resolvePath('/' . self::TEST_TRASHBIN_USER1 . '/files/folder');
653
+        if ($storage instanceof Local) {
654
+            $folderAbsPath = $storage->getSourcePath($internalPath);
655
+            // make folder read-only
656
+            chmod($folderAbsPath, 0555);
657
+
658
+            $this->assertTrue(
659
+                Trashbin::restore(
660
+                    'file1.txt.d' . $trashedFile->getMtime(),
661
+                    $trashedFile->getName(),
662
+                    $trashedFile->getMtime()
663
+                )
664
+            );
665
+
666
+            $file = $userFolder->get('file1.txt');
667
+            $this->assertEquals('foo', $file->getContent());
668
+
669
+            chmod($folderAbsPath, 0755);
670
+        }
671
+    }
672
+
673
+    /**
674
+     * @param string $user
675
+     * @param bool $create
676
+     */
677
+    public static function loginHelper($user, $create = false) {
678
+        if ($create) {
679
+            try {
680
+                Server::get(IUserManager::class)->createUser($user, $user);
681
+            } catch (\Exception $e) { // catch username is already being used from previous aborted runs
682
+            }
683
+        }
684
+
685
+        \OC_Util::tearDownFS();
686
+        \OC_User::setUserId('');
687
+        Filesystem::tearDown();
688
+        \OC_User::setUserId($user);
689
+        \OC_Util::setupFS($user);
690
+        \OC::$server->getUserFolder($user);
691
+    }
692 692
 }
693 693
 
694 694
 
695 695
 // just a dummy class to make protected methods available for testing
696 696
 class TrashbinForTesting extends Trashbin {
697 697
 
698
-	/**
699
-	 * @param FileInfo[] $files
700
-	 * @param integer $limit
701
-	 */
702
-	public function dummyDeleteExpiredFiles($files) {
703
-		// dummy value for $retention_obligation because it is not needed here
704
-		return parent::deleteExpiredFiles($files, TrashbinTest::TEST_TRASHBIN_USER1);
705
-	}
706
-
707
-	/**
708
-	 * @param FileInfo[] $files
709
-	 * @param integer $availableSpace
710
-	 */
711
-	public function dummyDeleteFiles($files, $availableSpace) {
712
-		return parent::deleteFiles($files, TrashbinTest::TEST_TRASHBIN_USER1, $availableSpace);
713
-	}
698
+    /**
699
+     * @param FileInfo[] $files
700
+     * @param integer $limit
701
+     */
702
+    public function dummyDeleteExpiredFiles($files) {
703
+        // dummy value for $retention_obligation because it is not needed here
704
+        return parent::deleteExpiredFiles($files, TrashbinTest::TEST_TRASHBIN_USER1);
705
+    }
706
+
707
+    /**
708
+     * @param FileInfo[] $files
709
+     * @param integer $availableSpace
710
+     */
711
+    public function dummyDeleteFiles($files, $availableSpace) {
712
+        return parent::deleteFiles($files, TrashbinTest::TEST_TRASHBIN_USER1, $availableSpace);
713
+    }
714 714
 }
Please login to merge, or discard this patch.
apps/dav/lib/Events/CalendarShareUpdatedEvent.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -20,64 +20,64 @@
 block discarded – undo
20 20
  * @psalm-import-type CalendarInfo from CalDavBackend
21 21
  */
22 22
 class CalendarShareUpdatedEvent extends Event {
23
-	/**
24
-	 * CalendarShareUpdatedEvent constructor.
25
-	 *
26
-	 * @param int $calendarId
27
-	 * @psalm-param CalendarInfo $calendarData
28
-	 * @param array $calendarData
29
-	 * @param list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}> $oldShares
30
-	 * @param list<array{href: string, commonName: string, readOnly: bool}> $added
31
-	 * @param list<string> $removed
32
-	 * @since 20.0.0
33
-	 */
34
-	public function __construct(
35
-		private int $calendarId,
36
-		private array $calendarData,
37
-		private array $oldShares,
38
-		private array $added,
39
-		private array $removed,
40
-	) {
41
-		parent::__construct();
42
-	}
23
+    /**
24
+     * CalendarShareUpdatedEvent constructor.
25
+     *
26
+     * @param int $calendarId
27
+     * @psalm-param CalendarInfo $calendarData
28
+     * @param array $calendarData
29
+     * @param list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}> $oldShares
30
+     * @param list<array{href: string, commonName: string, readOnly: bool}> $added
31
+     * @param list<string> $removed
32
+     * @since 20.0.0
33
+     */
34
+    public function __construct(
35
+        private int $calendarId,
36
+        private array $calendarData,
37
+        private array $oldShares,
38
+        private array $added,
39
+        private array $removed,
40
+    ) {
41
+        parent::__construct();
42
+    }
43 43
 
44
-	/**
45
-	 * @since 20.0.0
46
-	 */
47
-	public function getCalendarId(): int {
48
-		return $this->calendarId;
49
-	}
44
+    /**
45
+     * @since 20.0.0
46
+     */
47
+    public function getCalendarId(): int {
48
+        return $this->calendarId;
49
+    }
50 50
 
51
-	/**
52
-	 * @psalm-return CalendarInfo
53
-	 * @return array
54
-	 * @since 20.0.0
55
-	 */
56
-	public function getCalendarData(): array {
57
-		return $this->calendarData;
58
-	}
51
+    /**
52
+     * @psalm-return CalendarInfo
53
+     * @return array
54
+     * @since 20.0.0
55
+     */
56
+    public function getCalendarData(): array {
57
+        return $this->calendarData;
58
+    }
59 59
 
60
-	/**
61
-	 * @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
62
-	 * @since 20.0.0
63
-	 */
64
-	public function getOldShares(): array {
65
-		return $this->oldShares;
66
-	}
60
+    /**
61
+     * @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
62
+     * @since 20.0.0
63
+     */
64
+    public function getOldShares(): array {
65
+        return $this->oldShares;
66
+    }
67 67
 
68
-	/**
69
-	 * @return list<array{href: string, commonName: string, readOnly: bool}>
70
-	 * @since 20.0.0
71
-	 */
72
-	public function getAdded(): array {
73
-		return $this->added;
74
-	}
68
+    /**
69
+     * @return list<array{href: string, commonName: string, readOnly: bool}>
70
+     * @since 20.0.0
71
+     */
72
+    public function getAdded(): array {
73
+        return $this->added;
74
+    }
75 75
 
76
-	/**
77
-	 * @return list<string>
78
-	 * @since 20.0.0
79
-	 */
80
-	public function getRemoved(): array {
81
-		return $this->removed;
82
-	}
76
+    /**
77
+     * @return list<string>
78
+     * @since 20.0.0
79
+     */
80
+    public function getRemoved(): array {
81
+        return $this->removed;
82
+    }
83 83
 }
Please login to merge, or discard this patch.