Completed
Push — master ( bdce9c...1d50cf )
by
unknown
20:13
created
lib/private/Repair/RepairInvalidShares.php 2 patches
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -16,80 +16,80 @@
 block discarded – undo
16 16
  * Repairs shares with invalid data
17 17
  */
18 18
 class RepairInvalidShares implements IRepairStep {
19
-	public const CHUNK_SIZE = 200;
19
+    public const CHUNK_SIZE = 200;
20 20
 
21
-	public function __construct(
22
-		protected IConfig $config,
23
-		protected IDBConnection $connection,
24
-	) {
25
-	}
21
+    public function __construct(
22
+        protected IConfig $config,
23
+        protected IDBConnection $connection,
24
+    ) {
25
+    }
26 26
 
27
-	public function getName() {
28
-		return 'Repair invalid shares';
29
-	}
27
+    public function getName() {
28
+        return 'Repair invalid shares';
29
+    }
30 30
 
31
-	/**
32
-	 * Adjust file share permissions
33
-	 */
34
-	private function adjustFileSharePermissions(IOutput $output): void {
35
-		$mask = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE;
36
-		$builder = $this->connection->getQueryBuilder();
31
+    /**
32
+     * Adjust file share permissions
33
+     */
34
+    private function adjustFileSharePermissions(IOutput $output): void {
35
+        $mask = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE;
36
+        $builder = $this->connection->getQueryBuilder();
37 37
 
38
-		$permsFunc = $builder->expr()->bitwiseAnd('permissions', $mask);
39
-		$builder
40
-			->update('share')
41
-			->set('permissions', $permsFunc)
42
-			->where($builder->expr()->eq('item_type', $builder->expr()->literal('file')))
43
-			->andWhere($builder->expr()->neq('permissions', $permsFunc));
38
+        $permsFunc = $builder->expr()->bitwiseAnd('permissions', $mask);
39
+        $builder
40
+            ->update('share')
41
+            ->set('permissions', $permsFunc)
42
+            ->where($builder->expr()->eq('item_type', $builder->expr()->literal('file')))
43
+            ->andWhere($builder->expr()->neq('permissions', $permsFunc));
44 44
 
45
-		$updatedEntries = $builder->executeStatement();
46
-		if ($updatedEntries > 0) {
47
-			$output->info('Fixed file share permissions for ' . $updatedEntries . ' shares');
48
-		}
49
-	}
45
+        $updatedEntries = $builder->executeStatement();
46
+        if ($updatedEntries > 0) {
47
+            $output->info('Fixed file share permissions for ' . $updatedEntries . ' shares');
48
+        }
49
+    }
50 50
 
51
-	/**
52
-	 * Remove shares where the parent share does not exist anymore
53
-	 */
54
-	private function removeSharesNonExistingParent(IOutput $output): void {
55
-		$deletedEntries = 0;
51
+    /**
52
+     * Remove shares where the parent share does not exist anymore
53
+     */
54
+    private function removeSharesNonExistingParent(IOutput $output): void {
55
+        $deletedEntries = 0;
56 56
 
57
-		$query = $this->connection->getQueryBuilder();
58
-		$query->select('s1.parent')
59
-			->from('share', 's1')
60
-			->where($query->expr()->isNotNull('s1.parent'))
61
-			->andWhere($query->expr()->isNull('s2.id'))
62
-			->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'))
63
-			->groupBy('s1.parent')
64
-			->setMaxResults(self::CHUNK_SIZE);
57
+        $query = $this->connection->getQueryBuilder();
58
+        $query->select('s1.parent')
59
+            ->from('share', 's1')
60
+            ->where($query->expr()->isNotNull('s1.parent'))
61
+            ->andWhere($query->expr()->isNull('s2.id'))
62
+            ->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'))
63
+            ->groupBy('s1.parent')
64
+            ->setMaxResults(self::CHUNK_SIZE);
65 65
 
66
-		$deleteQuery = $this->connection->getQueryBuilder();
67
-		$deleteQuery->delete('share')
68
-			->where($deleteQuery->expr()->eq('parent', $deleteQuery->createParameter('parent')));
66
+        $deleteQuery = $this->connection->getQueryBuilder();
67
+        $deleteQuery->delete('share')
68
+            ->where($deleteQuery->expr()->eq('parent', $deleteQuery->createParameter('parent')));
69 69
 
70
-		$deletedInLastChunk = self::CHUNK_SIZE;
71
-		while ($deletedInLastChunk === self::CHUNK_SIZE) {
72
-			$deletedInLastChunk = 0;
73
-			$result = $query->executeQuery();
74
-			while ($row = $result->fetch()) {
75
-				$deletedInLastChunk++;
76
-				$deletedEntries += $deleteQuery->setParameter('parent', (int)$row['parent'])
77
-					->executeStatement();
78
-			}
79
-			$result->closeCursor();
80
-		}
70
+        $deletedInLastChunk = self::CHUNK_SIZE;
71
+        while ($deletedInLastChunk === self::CHUNK_SIZE) {
72
+            $deletedInLastChunk = 0;
73
+            $result = $query->executeQuery();
74
+            while ($row = $result->fetch()) {
75
+                $deletedInLastChunk++;
76
+                $deletedEntries += $deleteQuery->setParameter('parent', (int)$row['parent'])
77
+                    ->executeStatement();
78
+            }
79
+            $result->closeCursor();
80
+        }
81 81
 
82
-		if ($deletedEntries) {
83
-			$output->info('Removed ' . $deletedEntries . ' shares where the parent did not exist');
84
-		}
85
-	}
82
+        if ($deletedEntries) {
83
+            $output->info('Removed ' . $deletedEntries . ' shares where the parent did not exist');
84
+        }
85
+    }
86 86
 
87
-	public function run(IOutput $output) {
88
-		$ocVersionFromBeforeUpdate = $this->config->getSystemValueString('version', '0.0.0');
89
-		if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.11', '<')) {
90
-			$this->adjustFileSharePermissions($output);
91
-		}
87
+    public function run(IOutput $output) {
88
+        $ocVersionFromBeforeUpdate = $this->config->getSystemValueString('version', '0.0.0');
89
+        if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.11', '<')) {
90
+            $this->adjustFileSharePermissions($output);
91
+        }
92 92
 
93
-		$this->removeSharesNonExistingParent($output);
94
-	}
93
+        $this->removeSharesNonExistingParent($output);
94
+    }
95 95
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
 
45 45
 		$updatedEntries = $builder->executeStatement();
46 46
 		if ($updatedEntries > 0) {
47
-			$output->info('Fixed file share permissions for ' . $updatedEntries . ' shares');
47
+			$output->info('Fixed file share permissions for '.$updatedEntries.' shares');
48 48
 		}
49 49
 	}
50 50
 
@@ -73,14 +73,14 @@  discard block
 block discarded – undo
73 73
 			$result = $query->executeQuery();
74 74
 			while ($row = $result->fetch()) {
75 75
 				$deletedInLastChunk++;
76
-				$deletedEntries += $deleteQuery->setParameter('parent', (int)$row['parent'])
76
+				$deletedEntries += $deleteQuery->setParameter('parent', (int) $row['parent'])
77 77
 					->executeStatement();
78 78
 			}
79 79
 			$result->closeCursor();
80 80
 		}
81 81
 
82 82
 		if ($deletedEntries) {
83
-			$output->info('Removed ' . $deletedEntries . ' shares where the parent did not exist');
83
+			$output->info('Removed '.$deletedEntries.' shares where the parent did not exist');
84 84
 		}
85 85
 	}
86 86
 
Please login to merge, or discard this patch.
lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php 2 patches
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -19,73 +19,73 @@
 block discarded – undo
19 19
 use Psr\Log\LoggerInterface;
20 20
 
21 21
 class CleanPreviewsBackgroundJob extends QueuedJob {
22
-	public function __construct(
23
-		private IRootFolder $rootFolder,
24
-		private LoggerInterface $logger,
25
-		private IJobList $jobList,
26
-		ITimeFactory $timeFactory,
27
-		private IUserManager $userManager,
28
-	) {
29
-		parent::__construct($timeFactory);
30
-	}
22
+    public function __construct(
23
+        private IRootFolder $rootFolder,
24
+        private LoggerInterface $logger,
25
+        private IJobList $jobList,
26
+        ITimeFactory $timeFactory,
27
+        private IUserManager $userManager,
28
+    ) {
29
+        parent::__construct($timeFactory);
30
+    }
31 31
 
32
-	public function run($argument): void {
33
-		$uid = $argument['uid'];
34
-		if (!$this->userManager->userExists($uid)) {
35
-			$this->logger->info('User no longer exists, skip user ' . $uid);
36
-			return;
37
-		}
38
-		$this->logger->info('Started preview cleanup for ' . $uid);
39
-		$empty = $this->cleanupPreviews($uid);
32
+    public function run($argument): void {
33
+        $uid = $argument['uid'];
34
+        if (!$this->userManager->userExists($uid)) {
35
+            $this->logger->info('User no longer exists, skip user ' . $uid);
36
+            return;
37
+        }
38
+        $this->logger->info('Started preview cleanup for ' . $uid);
39
+        $empty = $this->cleanupPreviews($uid);
40 40
 
41
-		if (!$empty) {
42
-			$this->jobList->add(self::class, ['uid' => $uid]);
43
-			$this->logger->info('New preview cleanup scheduled for ' . $uid);
44
-		} else {
45
-			$this->logger->info('Preview cleanup done for ' . $uid);
46
-		}
47
-	}
41
+        if (!$empty) {
42
+            $this->jobList->add(self::class, ['uid' => $uid]);
43
+            $this->logger->info('New preview cleanup scheduled for ' . $uid);
44
+        } else {
45
+            $this->logger->info('Preview cleanup done for ' . $uid);
46
+        }
47
+    }
48 48
 
49
-	/**
50
-	 * @param string $uid
51
-	 */
52
-	private function cleanupPreviews($uid): bool {
53
-		try {
54
-			$userFolder = $this->rootFolder->getUserFolder($uid);
55
-		} catch (NotFoundException $e) {
56
-			return true;
57
-		}
49
+    /**
50
+     * @param string $uid
51
+     */
52
+    private function cleanupPreviews($uid): bool {
53
+        try {
54
+            $userFolder = $this->rootFolder->getUserFolder($uid);
55
+        } catch (NotFoundException $e) {
56
+            return true;
57
+        }
58 58
 
59
-		$userRoot = $userFolder->getParent();
59
+        $userRoot = $userFolder->getParent();
60 60
 
61
-		try {
62
-			/** @var Folder $thumbnailFolder */
63
-			$thumbnailFolder = $userRoot->get('thumbnails');
64
-		} catch (NotFoundException $e) {
65
-			return true;
66
-		}
61
+        try {
62
+            /** @var Folder $thumbnailFolder */
63
+            $thumbnailFolder = $userRoot->get('thumbnails');
64
+        } catch (NotFoundException $e) {
65
+            return true;
66
+        }
67 67
 
68
-		$thumbnails = $thumbnailFolder->getDirectoryListing();
68
+        $thumbnails = $thumbnailFolder->getDirectoryListing();
69 69
 
70
-		$start = $this->time->getTime();
71
-		foreach ($thumbnails as $thumbnail) {
72
-			try {
73
-				$thumbnail->delete();
74
-			} catch (NotPermittedException $e) {
75
-				// Ignore
76
-			}
70
+        $start = $this->time->getTime();
71
+        foreach ($thumbnails as $thumbnail) {
72
+            try {
73
+                $thumbnail->delete();
74
+            } catch (NotPermittedException $e) {
75
+                // Ignore
76
+            }
77 77
 
78
-			if (($this->time->getTime() - $start) > 15) {
79
-				return false;
80
-			}
81
-		}
78
+            if (($this->time->getTime() - $start) > 15) {
79
+                return false;
80
+            }
81
+        }
82 82
 
83
-		try {
84
-			$thumbnailFolder->delete();
85
-		} catch (NotPermittedException $e) {
86
-			// Ignore
87
-		}
83
+        try {
84
+            $thumbnailFolder->delete();
85
+        } catch (NotPermittedException $e) {
86
+            // Ignore
87
+        }
88 88
 
89
-		return true;
90
-	}
89
+        return true;
90
+    }
91 91
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -32,17 +32,17 @@
 block discarded – undo
32 32
 	public function run($argument): void {
33 33
 		$uid = $argument['uid'];
34 34
 		if (!$this->userManager->userExists($uid)) {
35
-			$this->logger->info('User no longer exists, skip user ' . $uid);
35
+			$this->logger->info('User no longer exists, skip user '.$uid);
36 36
 			return;
37 37
 		}
38
-		$this->logger->info('Started preview cleanup for ' . $uid);
38
+		$this->logger->info('Started preview cleanup for '.$uid);
39 39
 		$empty = $this->cleanupPreviews($uid);
40 40
 
41 41
 		if (!$empty) {
42 42
 			$this->jobList->add(self::class, ['uid' => $uid]);
43
-			$this->logger->info('New preview cleanup scheduled for ' . $uid);
43
+			$this->logger->info('New preview cleanup scheduled for '.$uid);
44 44
 		} else {
45
-			$this->logger->info('Preview cleanup done for ' . $uid);
45
+			$this->logger->info('Preview cleanup done for '.$uid);
46 46
 		}
47 47
 	}
48 48
 
Please login to merge, or discard this patch.
lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php 1 patch
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -20,76 +20,76 @@
 block discarded – undo
20 20
 use function is_resource;
21 21
 
22 22
 class MoveAvatarsBackgroundJob extends QueuedJob {
23
-	private ?IStorage $owncloudAvatarStorage = null;
23
+    private ?IStorage $owncloudAvatarStorage = null;
24 24
 
25
-	public function __construct(
26
-		private IUserManager $userManager,
27
-		private LoggerInterface $logger,
28
-		private IAvatarManager $avatarManager,
29
-		private IRootFolder $rootFolder,
30
-		ITimeFactory $time,
31
-	) {
32
-		parent::__construct($time);
33
-		try {
34
-			$this->owncloudAvatarStorage = $rootFolder->get('avatars')->getStorage();
35
-		} catch (\Exception $e) {
36
-		}
37
-	}
25
+    public function __construct(
26
+        private IUserManager $userManager,
27
+        private LoggerInterface $logger,
28
+        private IAvatarManager $avatarManager,
29
+        private IRootFolder $rootFolder,
30
+        ITimeFactory $time,
31
+    ) {
32
+        parent::__construct($time);
33
+        try {
34
+            $this->owncloudAvatarStorage = $rootFolder->get('avatars')->getStorage();
35
+        } catch (\Exception $e) {
36
+        }
37
+    }
38 38
 
39
-	public function run($argument) {
40
-		$this->logger->info('Started migrating avatars to AppData folder');
41
-		$this->moveAvatars();
42
-		$this->logger->info('All avatars migrated to AppData folder');
43
-	}
39
+    public function run($argument) {
40
+        $this->logger->info('Started migrating avatars to AppData folder');
41
+        $this->moveAvatars();
42
+        $this->logger->info('All avatars migrated to AppData folder');
43
+    }
44 44
 
45
-	private function moveAvatars(): void {
46
-		if (!$this->owncloudAvatarStorage) {
47
-			$this->logger->info('No legacy avatars available, skipping migration');
48
-			return;
49
-		}
45
+    private function moveAvatars(): void {
46
+        if (!$this->owncloudAvatarStorage) {
47
+            $this->logger->info('No legacy avatars available, skipping migration');
48
+            return;
49
+        }
50 50
 
51
-		$counter = 0;
52
-		$this->userManager->callForSeenUsers(function (IUser $user) use (&$counter) {
53
-			$uid = $user->getUID();
51
+        $counter = 0;
52
+        $this->userManager->callForSeenUsers(function (IUser $user) use (&$counter) {
53
+            $uid = $user->getUID();
54 54
 
55
-			$path = 'avatars/' . $this->buildOwnCloudAvatarPath($uid);
56
-			$avatar = $this->avatarManager->getAvatar($uid);
57
-			try {
58
-				$avatarPath = $path . '/avatar.' . $this->getExtension($path);
59
-				$resource = $this->owncloudAvatarStorage->fopen($avatarPath, 'r');
60
-				if (is_resource($resource)) {
61
-					$avatar->set($resource);
62
-					fclose($resource);
63
-				} else {
64
-					throw new \Exception('Failed to open old avatar file for reading');
65
-				}
66
-			} catch (NotFoundException $e) {
67
-				// In case there is no avatar we can just skip
68
-			} catch (\Throwable $e) {
69
-				$this->logger->error('Failed to migrate avatar for user ' . $uid, ['exception' => $e]);
70
-			}
55
+            $path = 'avatars/' . $this->buildOwnCloudAvatarPath($uid);
56
+            $avatar = $this->avatarManager->getAvatar($uid);
57
+            try {
58
+                $avatarPath = $path . '/avatar.' . $this->getExtension($path);
59
+                $resource = $this->owncloudAvatarStorage->fopen($avatarPath, 'r');
60
+                if (is_resource($resource)) {
61
+                    $avatar->set($resource);
62
+                    fclose($resource);
63
+                } else {
64
+                    throw new \Exception('Failed to open old avatar file for reading');
65
+                }
66
+            } catch (NotFoundException $e) {
67
+                // In case there is no avatar we can just skip
68
+            } catch (\Throwable $e) {
69
+                $this->logger->error('Failed to migrate avatar for user ' . $uid, ['exception' => $e]);
70
+            }
71 71
 
72
-			$counter++;
73
-			if ($counter % 100 === 0) {
74
-				$this->logger->info('{amount} avatars migrated', ['amount' => $counter]);
75
-			}
76
-		});
77
-	}
72
+            $counter++;
73
+            if ($counter % 100 === 0) {
74
+                $this->logger->info('{amount} avatars migrated', ['amount' => $counter]);
75
+            }
76
+        });
77
+    }
78 78
 
79
-	/**
80
-	 * @throws NotFoundException
81
-	 */
82
-	private function getExtension(string $path): string {
83
-		if ($this->owncloudAvatarStorage->file_exists("{$path}/avatar.jpg")) {
84
-			return 'jpg';
85
-		}
86
-		if ($this->owncloudAvatarStorage->file_exists("{$path}/avatar.png")) {
87
-			return 'png';
88
-		}
89
-		throw new NotFoundException("{$path}/avatar.jpg|png");
90
-	}
79
+    /**
80
+     * @throws NotFoundException
81
+     */
82
+    private function getExtension(string $path): string {
83
+        if ($this->owncloudAvatarStorage->file_exists("{$path}/avatar.jpg")) {
84
+            return 'jpg';
85
+        }
86
+        if ($this->owncloudAvatarStorage->file_exists("{$path}/avatar.png")) {
87
+            return 'png';
88
+        }
89
+        throw new NotFoundException("{$path}/avatar.jpg|png");
90
+    }
91 91
 
92
-	protected function buildOwnCloudAvatarPath(string $userId): string {
93
-		return substr_replace(substr_replace(md5($userId), '/', 4, 0), '/', 2, 0);
94
-	}
92
+    protected function buildOwnCloudAvatarPath(string $userId): string {
93
+        return substr_replace(substr_replace(md5($userId), '/', 4, 0), '/', 2, 0);
94
+    }
95 95
 }
Please login to merge, or discard this patch.
lib/private/Repair/RepairMimeTypes.php 1 patch
Indentation   +469 added lines, -469 removed lines patch added patch discarded remove patch
@@ -17,473 +17,473 @@
 block discarded – undo
17 17
 use OCP\Migration\IRepairStep;
18 18
 
19 19
 class RepairMimeTypes implements IRepairStep {
20
-	private bool $dryRun = false;
21
-	private int $changeCount = 0;
22
-
23
-	/** @var int */
24
-	protected int $folderMimeTypeId;
25
-
26
-	public function __construct(
27
-		protected IConfig $config,
28
-		protected IAppConfig $appConfig,
29
-		protected IDBConnection $connection,
30
-	) {
31
-	}
32
-
33
-	public function getName(): string {
34
-		return 'Repair mime types';
35
-	}
36
-
37
-	/**
38
-	 * @throws Exception
39
-	 */
40
-	private function updateMimetypes($updatedMimetypes): IResult|int|null {
41
-		if ($this->dryRun) {
42
-			$this->changeCount += count($updatedMimetypes);
43
-			return null;
44
-		}
45
-
46
-		$query = $this->connection->getQueryBuilder();
47
-		$query->select('id')
48
-			->from('mimetypes')
49
-			->where($query->expr()->eq('mimetype', $query->createParameter('mimetype'), IQueryBuilder::PARAM_INT));
50
-		$insert = $this->connection->getQueryBuilder();
51
-		$insert->insert('mimetypes')
52
-			->setValue('mimetype', $insert->createParameter('mimetype'));
53
-
54
-		if (empty($this->folderMimeTypeId)) {
55
-			$query->setParameter('mimetype', 'httpd/unix-directory');
56
-			$result = $query->execute();
57
-			$this->folderMimeTypeId = (int)$result->fetchOne();
58
-			$result->closeCursor();
59
-		}
60
-
61
-		$update = $this->connection->getQueryBuilder();
62
-		$update->update('filecache')
63
-			->runAcrossAllShards()
64
-			->set('mimetype', $update->createParameter('mimetype'))
65
-			->where($update->expr()->neq('mimetype', $update->createParameter('mimetype'), IQueryBuilder::PARAM_INT))
66
-			->andWhere($update->expr()->neq('mimetype', $update->createParameter('folder'), IQueryBuilder::PARAM_INT))
67
-			->andWhere($update->expr()->iLike('name', $update->createParameter('name')))
68
-			->setParameter('folder', $this->folderMimeTypeId);
69
-
70
-		$count = 0;
71
-		foreach ($updatedMimetypes as $extension => $mimetype) {
72
-			// get target mimetype id
73
-			$query->setParameter('mimetype', $mimetype);
74
-			$result = $query->execute();
75
-			$mimetypeId = (int)$result->fetchOne();
76
-			$result->closeCursor();
77
-
78
-			if (!$mimetypeId) {
79
-				// insert mimetype
80
-				$insert->setParameter('mimetype', $mimetype);
81
-				$insert->execute();
82
-				$mimetypeId = $insert->getLastInsertId();
83
-			}
84
-
85
-			// change mimetype for files with x extension
86
-			$update->setParameter('mimetype', $mimetypeId)
87
-				->setParameter('name', '%' . $this->connection->escapeLikeParameter('.' . $extension));
88
-			$count += $update->execute();
89
-		}
90
-
91
-		return $count;
92
-	}
93
-
94
-	/**
95
-	 * @throws Exception
96
-	 * @since 12.0.0.14
97
-	 */
98
-	private function introduceImageTypes(): IResult|int|null {
99
-		$updatedMimetypes = [
100
-			'jp2' => 'image/jp2',
101
-			'webp' => 'image/webp',
102
-		];
103
-
104
-		return $this->updateMimetypes($updatedMimetypes);
105
-	}
106
-
107
-	/**
108
-	 * @throws Exception
109
-	 * @since 12.0.0.13
110
-	 */
111
-	private function introduceWindowsProgramTypes(): IResult|int|null {
112
-		$updatedMimetypes = [
113
-			'htaccess' => 'text/plain',
114
-			'bat' => 'application/x-msdos-program',
115
-			'cmd' => 'application/cmd',
116
-		];
117
-
118
-		return $this->updateMimetypes($updatedMimetypes);
119
-	}
120
-
121
-	/**
122
-	 * @throws Exception
123
-	 * @since 13.0.0.0
124
-	 */
125
-	private function introduceLocationTypes(): IResult|int|null {
126
-		$updatedMimetypes = [
127
-			'gpx' => 'application/gpx+xml',
128
-			'kml' => 'application/vnd.google-earth.kml+xml',
129
-			'kmz' => 'application/vnd.google-earth.kmz',
130
-			'tcx' => 'application/vnd.garmin.tcx+xml',
131
-		];
132
-
133
-		return $this->updateMimetypes($updatedMimetypes);
134
-	}
135
-
136
-	/**
137
-	 * @throws Exception
138
-	 * @since 13.0.0.3
139
-	 */
140
-	private function introduceInternetShortcutTypes(): IResult|int|null {
141
-		$updatedMimetypes = [
142
-			'url' => 'application/internet-shortcut',
143
-			'webloc' => 'application/internet-shortcut'
144
-		];
145
-
146
-		return $this->updateMimetypes($updatedMimetypes);
147
-	}
148
-
149
-	/**
150
-	 * @throws Exception
151
-	 * @since 13.0.0.6
152
-	 */
153
-	private function introduceStreamingTypes(): IResult|int|null {
154
-		$updatedMimetypes = [
155
-			'm3u' => 'audio/mpegurl',
156
-			'm3u8' => 'audio/mpegurl',
157
-			'pls' => 'audio/x-scpls'
158
-		];
159
-
160
-		return $this->updateMimetypes($updatedMimetypes);
161
-	}
162
-
163
-	/**
164
-	 * @throws Exception
165
-	 * @since 14.0.0.8
166
-	 */
167
-	private function introduceVisioTypes(): IResult|int|null {
168
-		$updatedMimetypes = [
169
-			'vsdm' => 'application/vnd.visio',
170
-			'vsdx' => 'application/vnd.visio',
171
-			'vssm' => 'application/vnd.visio',
172
-			'vssx' => 'application/vnd.visio',
173
-			'vstm' => 'application/vnd.visio',
174
-			'vstx' => 'application/vnd.visio',
175
-		];
176
-
177
-		return $this->updateMimetypes($updatedMimetypes);
178
-	}
179
-
180
-	/**
181
-	 * @throws Exception
182
-	 * @since 14.0.0.10
183
-	 */
184
-	private function introduceComicbookTypes(): IResult|int|null {
185
-		$updatedMimetypes = [
186
-			'cb7' => 'application/comicbook+7z',
187
-			'cba' => 'application/comicbook+ace',
188
-			'cbr' => 'application/comicbook+rar',
189
-			'cbt' => 'application/comicbook+tar',
190
-			'cbtc' => 'application/comicbook+truecrypt',
191
-			'cbz' => 'application/comicbook+zip',
192
-		];
193
-
194
-		return $this->updateMimetypes($updatedMimetypes);
195
-	}
196
-
197
-	/**
198
-	 * @throws Exception
199
-	 * @since 20.0.0.5
200
-	 */
201
-	private function introduceOpenDocumentTemplates(): IResult|int|null {
202
-		$updatedMimetypes = [
203
-			'ott' => 'application/vnd.oasis.opendocument.text-template',
204
-			'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
205
-			'otp' => 'application/vnd.oasis.opendocument.presentation-template',
206
-			'otg' => 'application/vnd.oasis.opendocument.graphics-template',
207
-		];
208
-
209
-		return $this->updateMimetypes($updatedMimetypes);
210
-	}
211
-
212
-	/**
213
-	 * @throws Exception
214
-	 * @since 21.0.0.7
215
-	 */
216
-	private function introduceOrgModeType(): IResult|int|null {
217
-		$updatedMimetypes = [
218
-			'org' => 'text/org'
219
-		];
220
-
221
-		return $this->updateMimetypes($updatedMimetypes);
222
-	}
223
-
224
-	/**
225
-	 * @throws Exception
226
-	 * @since 23.0.0.2
227
-	 */
228
-	private function introduceFlatOpenDocumentType(): IResult|int|null {
229
-		$updatedMimetypes = [
230
-			'fodt' => 'application/vnd.oasis.opendocument.text-flat-xml',
231
-			'fods' => 'application/vnd.oasis.opendocument.spreadsheet-flat-xml',
232
-			'fodg' => 'application/vnd.oasis.opendocument.graphics-flat-xml',
233
-			'fodp' => 'application/vnd.oasis.opendocument.presentation-flat-xml',
234
-		];
235
-
236
-		return $this->updateMimetypes($updatedMimetypes);
237
-	}
238
-
239
-	/**
240
-	 * @throws Exception
241
-	 * @since 25.0.0.2
242
-	 */
243
-	private function introduceOnlyofficeFormType(): IResult|int|null {
244
-		$updatedMimetypes = [
245
-			'oform' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform',
246
-			'docxf' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf',
247
-		];
248
-
249
-		return $this->updateMimetypes($updatedMimetypes);
250
-	}
251
-
252
-	/**
253
-	 * @throws Exception
254
-	 * @since 26.0.0.1
255
-	 */
256
-	private function introduceAsciidocType(): IResult|int|null {
257
-		$updatedMimetypes = [
258
-			'adoc' => 'text/asciidoc',
259
-			'asciidoc' => 'text/asciidoc',
260
-		];
261
-
262
-		return $this->updateMimetypes($updatedMimetypes);
263
-	}
264
-
265
-	/**
266
-	 * @throws Exception
267
-	 * @since 28.0.0.5
268
-	 */
269
-	private function introduceEnhancedMetafileFormatType(): IResult|int|null {
270
-		$updatedMimetypes = [
271
-			'emf' => 'image/emf',
272
-		];
273
-
274
-		return $this->updateMimetypes($updatedMimetypes);
275
-	}
276
-
277
-	/**
278
-	 * @throws Exception
279
-	 * @since 29.0.0.2
280
-	 */
281
-	private function introduceEmlAndMsgFormatType(): IResult|int|null {
282
-		$updatedMimetypes = [
283
-			'eml' => 'message/rfc822',
284
-			'msg' => 'application/vnd.ms-outlook',
285
-		];
286
-
287
-		return $this->updateMimetypes($updatedMimetypes);
288
-	}
289
-
290
-	/**
291
-	 * @throws Exception
292
-	 * @since 29.0.0.6
293
-	 */
294
-	private function introduceAacAudioType(): IResult|int|null {
295
-		$updatedMimetypes = [
296
-			'aac' => 'audio/aac',
297
-		];
298
-
299
-		return $this->updateMimetypes($updatedMimetypes);
300
-	}
301
-
302
-	/**
303
-	 * @throws Exception
304
-	 * @since 29.0.10
305
-	 */
306
-	private function introduceReStructuredTextFormatType(): IResult|int|null {
307
-		$updatedMimetypes = [
308
-			'rst' => 'text/x-rst',
309
-		];
310
-
311
-		return $this->updateMimetypes($updatedMimetypes);
312
-	}
313
-
314
-	/**
315
-	 * @throws Exception
316
-	 * @since 30.0.0
317
-	 */
318
-	private function introduceExcalidrawType(): IResult|int|null {
319
-		$updatedMimetypes = [
320
-			'excalidraw' => 'application/vnd.excalidraw+json',
321
-		];
322
-
323
-		return $this->updateMimetypes($updatedMimetypes);
324
-	}
325
-
326
-
327
-	/**
328
-	 * @throws Exception
329
-	 * @since 31.0.0
330
-	 */
331
-	private function introduceZstType(): IResult|int|null {
332
-		$updatedMimetypes = [
333
-			'zst' => 'application/zstd',
334
-			'nfo' => 'text/x-nfo',
335
-		];
336
-
337
-		return $this->updateMimetypes($updatedMimetypes);
338
-	}
339
-
340
-	/**
341
-	 * @throws Exception
342
-	 * @since 32.0.0
343
-	 */
344
-	private function introduceMusicxmlType(): IResult|int|null {
345
-		$updatedMimetypes = [
346
-			'mxl' => 'application/vnd.recordare.musicxml',
347
-			'musicxml' => 'application/vnd.recordare.musicxml+xml',
348
-		];
349
-
350
-		return $this->updateMimetypes($updatedMimetypes);
351
-	}
352
-
353
-	/**
354
-	 * @throws Exception
355
-	 * @since 32.0.0
356
-	 */
357
-	private function introduceTextType(): IResult|int|null {
358
-		$updatedMimetypes = [
359
-			'text' => 'text/plain',
360
-		];
361
-
362
-		return $this->updateMimetypes($updatedMimetypes);
363
-	}
364
-
365
-
366
-
367
-	/**
368
-	 * Check if there are any migrations available
369
-	 *
370
-	 * @throws Exception
371
-	 */
372
-	public function migrationsAvailable(): bool {
373
-		$this->dryRun = true;
374
-		$this->run(new NullOutput());
375
-		$this->dryRun = false;
376
-		return $this->changeCount > 0;
377
-	}
378
-
379
-	/**
380
-	 * Get the current mimetype version
381
-	 */
382
-	private function getMimeTypeVersion(): string {
383
-		$serverVersion = $this->config->getSystemValueString('version', '0.0.0');
384
-		// 29.0.0.10 is the last version with a mimetype migration before it was moved to a separate version number
385
-		if (version_compare($serverVersion, '29.0.0.10', '>')) {
386
-			return $this->appConfig->getValueString('files', 'mimetype_version', '29.0.0.10');
387
-		}
388
-
389
-		return $serverVersion;
390
-	}
391
-
392
-	/**
393
-	 * Fix mime types
394
-	 *
395
-	 * @throws Exception
396
-	 */
397
-	public function run(IOutput $output): void {
398
-		$serverVersion = $this->config->getSystemValueString('version', '0.0.0');
399
-		$mimeTypeVersion = $this->getMimeTypeVersion();
400
-
401
-		// NOTE TO DEVELOPERS: when adding new mime types, please make sure to
402
-		// add a version comparison to avoid doing it every time
403
-		// PLEASE ALSO KEEP THE LIST SORTED BY VERSION NUMBER
404
-
405
-		if (version_compare($mimeTypeVersion, '12.0.0.14', '<') && $this->introduceImageTypes()) {
406
-			$output->info('Fixed image mime types');
407
-		}
408
-
409
-		if (version_compare($mimeTypeVersion, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
410
-			$output->info('Fixed windows program mime types');
411
-		}
412
-
413
-		if (version_compare($mimeTypeVersion, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
414
-			$output->info('Fixed geospatial mime types');
415
-		}
416
-
417
-		if (version_compare($mimeTypeVersion, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
418
-			$output->info('Fixed internet-shortcut mime types');
419
-		}
420
-
421
-		if (version_compare($mimeTypeVersion, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
422
-			$output->info('Fixed streaming mime types');
423
-		}
424
-
425
-		if (version_compare($mimeTypeVersion, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
426
-			$output->info('Fixed visio mime types');
427
-		}
428
-
429
-		if (version_compare($mimeTypeVersion, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
430
-			$output->info('Fixed comicbook mime types');
431
-		}
432
-
433
-		if (version_compare($mimeTypeVersion, '20.0.0.5', '<') && $this->introduceOpenDocumentTemplates()) {
434
-			$output->info('Fixed OpenDocument template mime types');
435
-		}
436
-
437
-		if (version_compare($mimeTypeVersion, '21.0.0.7', '<') && $this->introduceOrgModeType()) {
438
-			$output->info('Fixed orgmode mime types');
439
-		}
440
-
441
-		if (version_compare($mimeTypeVersion, '23.0.0.2', '<') && $this->introduceFlatOpenDocumentType()) {
442
-			$output->info('Fixed Flat OpenDocument mime types');
443
-		}
444
-
445
-		if (version_compare($mimeTypeVersion, '25.0.0.2', '<') && $this->introduceOnlyofficeFormType()) {
446
-			$output->info('Fixed ONLYOFFICE Forms OpenXML mime types');
447
-		}
448
-
449
-		if (version_compare($mimeTypeVersion, '26.0.0.1', '<') && $this->introduceAsciidocType()) {
450
-			$output->info('Fixed AsciiDoc mime types');
451
-		}
452
-
453
-		if (version_compare($mimeTypeVersion, '28.0.0.5', '<') && $this->introduceEnhancedMetafileFormatType()) {
454
-			$output->info('Fixed Enhanced Metafile Format mime types');
455
-		}
456
-
457
-		if (version_compare($mimeTypeVersion, '29.0.0.2', '<') && $this->introduceEmlAndMsgFormatType()) {
458
-			$output->info('Fixed eml and msg mime type');
459
-		}
460
-
461
-		if (version_compare($mimeTypeVersion, '29.0.0.6', '<') && $this->introduceAacAudioType()) {
462
-			$output->info('Fixed aac mime type');
463
-		}
464
-
465
-		if (version_compare($mimeTypeVersion, '29.0.0.10', '<') && $this->introduceReStructuredTextFormatType()) {
466
-			$output->info('Fixed ReStructured Text mime type');
467
-		}
468
-
469
-		if (version_compare($mimeTypeVersion, '30.0.0.0', '<') && $this->introduceExcalidrawType()) {
470
-			$output->info('Fixed Excalidraw mime type');
471
-		}
472
-
473
-		if (version_compare($mimeTypeVersion, '31.0.0.0', '<') && $this->introduceZstType()) {
474
-			$output->info('Fixed zst mime type');
475
-		}
476
-
477
-		if (version_compare($mimeTypeVersion, '32.0.0.0', '<') && $this->introduceMusicxmlType()) {
478
-			$output->info('Fixed musicxml mime type');
479
-		}
480
-
481
-		if (version_compare($mimeTypeVersion, '32.0.0.0', '<') && $this->introduceTextType()) {
482
-			$out->info('Fixed text mime type');
483
-		}
484
-
485
-		if (!$this->dryRun) {
486
-			$this->appConfig->setValueString('files', 'mimetype_version', $serverVersion);
487
-		}
488
-	}
20
+    private bool $dryRun = false;
21
+    private int $changeCount = 0;
22
+
23
+    /** @var int */
24
+    protected int $folderMimeTypeId;
25
+
26
+    public function __construct(
27
+        protected IConfig $config,
28
+        protected IAppConfig $appConfig,
29
+        protected IDBConnection $connection,
30
+    ) {
31
+    }
32
+
33
+    public function getName(): string {
34
+        return 'Repair mime types';
35
+    }
36
+
37
+    /**
38
+     * @throws Exception
39
+     */
40
+    private function updateMimetypes($updatedMimetypes): IResult|int|null {
41
+        if ($this->dryRun) {
42
+            $this->changeCount += count($updatedMimetypes);
43
+            return null;
44
+        }
45
+
46
+        $query = $this->connection->getQueryBuilder();
47
+        $query->select('id')
48
+            ->from('mimetypes')
49
+            ->where($query->expr()->eq('mimetype', $query->createParameter('mimetype'), IQueryBuilder::PARAM_INT));
50
+        $insert = $this->connection->getQueryBuilder();
51
+        $insert->insert('mimetypes')
52
+            ->setValue('mimetype', $insert->createParameter('mimetype'));
53
+
54
+        if (empty($this->folderMimeTypeId)) {
55
+            $query->setParameter('mimetype', 'httpd/unix-directory');
56
+            $result = $query->execute();
57
+            $this->folderMimeTypeId = (int)$result->fetchOne();
58
+            $result->closeCursor();
59
+        }
60
+
61
+        $update = $this->connection->getQueryBuilder();
62
+        $update->update('filecache')
63
+            ->runAcrossAllShards()
64
+            ->set('mimetype', $update->createParameter('mimetype'))
65
+            ->where($update->expr()->neq('mimetype', $update->createParameter('mimetype'), IQueryBuilder::PARAM_INT))
66
+            ->andWhere($update->expr()->neq('mimetype', $update->createParameter('folder'), IQueryBuilder::PARAM_INT))
67
+            ->andWhere($update->expr()->iLike('name', $update->createParameter('name')))
68
+            ->setParameter('folder', $this->folderMimeTypeId);
69
+
70
+        $count = 0;
71
+        foreach ($updatedMimetypes as $extension => $mimetype) {
72
+            // get target mimetype id
73
+            $query->setParameter('mimetype', $mimetype);
74
+            $result = $query->execute();
75
+            $mimetypeId = (int)$result->fetchOne();
76
+            $result->closeCursor();
77
+
78
+            if (!$mimetypeId) {
79
+                // insert mimetype
80
+                $insert->setParameter('mimetype', $mimetype);
81
+                $insert->execute();
82
+                $mimetypeId = $insert->getLastInsertId();
83
+            }
84
+
85
+            // change mimetype for files with x extension
86
+            $update->setParameter('mimetype', $mimetypeId)
87
+                ->setParameter('name', '%' . $this->connection->escapeLikeParameter('.' . $extension));
88
+            $count += $update->execute();
89
+        }
90
+
91
+        return $count;
92
+    }
93
+
94
+    /**
95
+     * @throws Exception
96
+     * @since 12.0.0.14
97
+     */
98
+    private function introduceImageTypes(): IResult|int|null {
99
+        $updatedMimetypes = [
100
+            'jp2' => 'image/jp2',
101
+            'webp' => 'image/webp',
102
+        ];
103
+
104
+        return $this->updateMimetypes($updatedMimetypes);
105
+    }
106
+
107
+    /**
108
+     * @throws Exception
109
+     * @since 12.0.0.13
110
+     */
111
+    private function introduceWindowsProgramTypes(): IResult|int|null {
112
+        $updatedMimetypes = [
113
+            'htaccess' => 'text/plain',
114
+            'bat' => 'application/x-msdos-program',
115
+            'cmd' => 'application/cmd',
116
+        ];
117
+
118
+        return $this->updateMimetypes($updatedMimetypes);
119
+    }
120
+
121
+    /**
122
+     * @throws Exception
123
+     * @since 13.0.0.0
124
+     */
125
+    private function introduceLocationTypes(): IResult|int|null {
126
+        $updatedMimetypes = [
127
+            'gpx' => 'application/gpx+xml',
128
+            'kml' => 'application/vnd.google-earth.kml+xml',
129
+            'kmz' => 'application/vnd.google-earth.kmz',
130
+            'tcx' => 'application/vnd.garmin.tcx+xml',
131
+        ];
132
+
133
+        return $this->updateMimetypes($updatedMimetypes);
134
+    }
135
+
136
+    /**
137
+     * @throws Exception
138
+     * @since 13.0.0.3
139
+     */
140
+    private function introduceInternetShortcutTypes(): IResult|int|null {
141
+        $updatedMimetypes = [
142
+            'url' => 'application/internet-shortcut',
143
+            'webloc' => 'application/internet-shortcut'
144
+        ];
145
+
146
+        return $this->updateMimetypes($updatedMimetypes);
147
+    }
148
+
149
+    /**
150
+     * @throws Exception
151
+     * @since 13.0.0.6
152
+     */
153
+    private function introduceStreamingTypes(): IResult|int|null {
154
+        $updatedMimetypes = [
155
+            'm3u' => 'audio/mpegurl',
156
+            'm3u8' => 'audio/mpegurl',
157
+            'pls' => 'audio/x-scpls'
158
+        ];
159
+
160
+        return $this->updateMimetypes($updatedMimetypes);
161
+    }
162
+
163
+    /**
164
+     * @throws Exception
165
+     * @since 14.0.0.8
166
+     */
167
+    private function introduceVisioTypes(): IResult|int|null {
168
+        $updatedMimetypes = [
169
+            'vsdm' => 'application/vnd.visio',
170
+            'vsdx' => 'application/vnd.visio',
171
+            'vssm' => 'application/vnd.visio',
172
+            'vssx' => 'application/vnd.visio',
173
+            'vstm' => 'application/vnd.visio',
174
+            'vstx' => 'application/vnd.visio',
175
+        ];
176
+
177
+        return $this->updateMimetypes($updatedMimetypes);
178
+    }
179
+
180
+    /**
181
+     * @throws Exception
182
+     * @since 14.0.0.10
183
+     */
184
+    private function introduceComicbookTypes(): IResult|int|null {
185
+        $updatedMimetypes = [
186
+            'cb7' => 'application/comicbook+7z',
187
+            'cba' => 'application/comicbook+ace',
188
+            'cbr' => 'application/comicbook+rar',
189
+            'cbt' => 'application/comicbook+tar',
190
+            'cbtc' => 'application/comicbook+truecrypt',
191
+            'cbz' => 'application/comicbook+zip',
192
+        ];
193
+
194
+        return $this->updateMimetypes($updatedMimetypes);
195
+    }
196
+
197
+    /**
198
+     * @throws Exception
199
+     * @since 20.0.0.5
200
+     */
201
+    private function introduceOpenDocumentTemplates(): IResult|int|null {
202
+        $updatedMimetypes = [
203
+            'ott' => 'application/vnd.oasis.opendocument.text-template',
204
+            'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
205
+            'otp' => 'application/vnd.oasis.opendocument.presentation-template',
206
+            'otg' => 'application/vnd.oasis.opendocument.graphics-template',
207
+        ];
208
+
209
+        return $this->updateMimetypes($updatedMimetypes);
210
+    }
211
+
212
+    /**
213
+     * @throws Exception
214
+     * @since 21.0.0.7
215
+     */
216
+    private function introduceOrgModeType(): IResult|int|null {
217
+        $updatedMimetypes = [
218
+            'org' => 'text/org'
219
+        ];
220
+
221
+        return $this->updateMimetypes($updatedMimetypes);
222
+    }
223
+
224
+    /**
225
+     * @throws Exception
226
+     * @since 23.0.0.2
227
+     */
228
+    private function introduceFlatOpenDocumentType(): IResult|int|null {
229
+        $updatedMimetypes = [
230
+            'fodt' => 'application/vnd.oasis.opendocument.text-flat-xml',
231
+            'fods' => 'application/vnd.oasis.opendocument.spreadsheet-flat-xml',
232
+            'fodg' => 'application/vnd.oasis.opendocument.graphics-flat-xml',
233
+            'fodp' => 'application/vnd.oasis.opendocument.presentation-flat-xml',
234
+        ];
235
+
236
+        return $this->updateMimetypes($updatedMimetypes);
237
+    }
238
+
239
+    /**
240
+     * @throws Exception
241
+     * @since 25.0.0.2
242
+     */
243
+    private function introduceOnlyofficeFormType(): IResult|int|null {
244
+        $updatedMimetypes = [
245
+            'oform' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform',
246
+            'docxf' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf',
247
+        ];
248
+
249
+        return $this->updateMimetypes($updatedMimetypes);
250
+    }
251
+
252
+    /**
253
+     * @throws Exception
254
+     * @since 26.0.0.1
255
+     */
256
+    private function introduceAsciidocType(): IResult|int|null {
257
+        $updatedMimetypes = [
258
+            'adoc' => 'text/asciidoc',
259
+            'asciidoc' => 'text/asciidoc',
260
+        ];
261
+
262
+        return $this->updateMimetypes($updatedMimetypes);
263
+    }
264
+
265
+    /**
266
+     * @throws Exception
267
+     * @since 28.0.0.5
268
+     */
269
+    private function introduceEnhancedMetafileFormatType(): IResult|int|null {
270
+        $updatedMimetypes = [
271
+            'emf' => 'image/emf',
272
+        ];
273
+
274
+        return $this->updateMimetypes($updatedMimetypes);
275
+    }
276
+
277
+    /**
278
+     * @throws Exception
279
+     * @since 29.0.0.2
280
+     */
281
+    private function introduceEmlAndMsgFormatType(): IResult|int|null {
282
+        $updatedMimetypes = [
283
+            'eml' => 'message/rfc822',
284
+            'msg' => 'application/vnd.ms-outlook',
285
+        ];
286
+
287
+        return $this->updateMimetypes($updatedMimetypes);
288
+    }
289
+
290
+    /**
291
+     * @throws Exception
292
+     * @since 29.0.0.6
293
+     */
294
+    private function introduceAacAudioType(): IResult|int|null {
295
+        $updatedMimetypes = [
296
+            'aac' => 'audio/aac',
297
+        ];
298
+
299
+        return $this->updateMimetypes($updatedMimetypes);
300
+    }
301
+
302
+    /**
303
+     * @throws Exception
304
+     * @since 29.0.10
305
+     */
306
+    private function introduceReStructuredTextFormatType(): IResult|int|null {
307
+        $updatedMimetypes = [
308
+            'rst' => 'text/x-rst',
309
+        ];
310
+
311
+        return $this->updateMimetypes($updatedMimetypes);
312
+    }
313
+
314
+    /**
315
+     * @throws Exception
316
+     * @since 30.0.0
317
+     */
318
+    private function introduceExcalidrawType(): IResult|int|null {
319
+        $updatedMimetypes = [
320
+            'excalidraw' => 'application/vnd.excalidraw+json',
321
+        ];
322
+
323
+        return $this->updateMimetypes($updatedMimetypes);
324
+    }
325
+
326
+
327
+    /**
328
+     * @throws Exception
329
+     * @since 31.0.0
330
+     */
331
+    private function introduceZstType(): IResult|int|null {
332
+        $updatedMimetypes = [
333
+            'zst' => 'application/zstd',
334
+            'nfo' => 'text/x-nfo',
335
+        ];
336
+
337
+        return $this->updateMimetypes($updatedMimetypes);
338
+    }
339
+
340
+    /**
341
+     * @throws Exception
342
+     * @since 32.0.0
343
+     */
344
+    private function introduceMusicxmlType(): IResult|int|null {
345
+        $updatedMimetypes = [
346
+            'mxl' => 'application/vnd.recordare.musicxml',
347
+            'musicxml' => 'application/vnd.recordare.musicxml+xml',
348
+        ];
349
+
350
+        return $this->updateMimetypes($updatedMimetypes);
351
+    }
352
+
353
+    /**
354
+     * @throws Exception
355
+     * @since 32.0.0
356
+     */
357
+    private function introduceTextType(): IResult|int|null {
358
+        $updatedMimetypes = [
359
+            'text' => 'text/plain',
360
+        ];
361
+
362
+        return $this->updateMimetypes($updatedMimetypes);
363
+    }
364
+
365
+
366
+
367
+    /**
368
+     * Check if there are any migrations available
369
+     *
370
+     * @throws Exception
371
+     */
372
+    public function migrationsAvailable(): bool {
373
+        $this->dryRun = true;
374
+        $this->run(new NullOutput());
375
+        $this->dryRun = false;
376
+        return $this->changeCount > 0;
377
+    }
378
+
379
+    /**
380
+     * Get the current mimetype version
381
+     */
382
+    private function getMimeTypeVersion(): string {
383
+        $serverVersion = $this->config->getSystemValueString('version', '0.0.0');
384
+        // 29.0.0.10 is the last version with a mimetype migration before it was moved to a separate version number
385
+        if (version_compare($serverVersion, '29.0.0.10', '>')) {
386
+            return $this->appConfig->getValueString('files', 'mimetype_version', '29.0.0.10');
387
+        }
388
+
389
+        return $serverVersion;
390
+    }
391
+
392
+    /**
393
+     * Fix mime types
394
+     *
395
+     * @throws Exception
396
+     */
397
+    public function run(IOutput $output): void {
398
+        $serverVersion = $this->config->getSystemValueString('version', '0.0.0');
399
+        $mimeTypeVersion = $this->getMimeTypeVersion();
400
+
401
+        // NOTE TO DEVELOPERS: when adding new mime types, please make sure to
402
+        // add a version comparison to avoid doing it every time
403
+        // PLEASE ALSO KEEP THE LIST SORTED BY VERSION NUMBER
404
+
405
+        if (version_compare($mimeTypeVersion, '12.0.0.14', '<') && $this->introduceImageTypes()) {
406
+            $output->info('Fixed image mime types');
407
+        }
408
+
409
+        if (version_compare($mimeTypeVersion, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
410
+            $output->info('Fixed windows program mime types');
411
+        }
412
+
413
+        if (version_compare($mimeTypeVersion, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
414
+            $output->info('Fixed geospatial mime types');
415
+        }
416
+
417
+        if (version_compare($mimeTypeVersion, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
418
+            $output->info('Fixed internet-shortcut mime types');
419
+        }
420
+
421
+        if (version_compare($mimeTypeVersion, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
422
+            $output->info('Fixed streaming mime types');
423
+        }
424
+
425
+        if (version_compare($mimeTypeVersion, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
426
+            $output->info('Fixed visio mime types');
427
+        }
428
+
429
+        if (version_compare($mimeTypeVersion, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
430
+            $output->info('Fixed comicbook mime types');
431
+        }
432
+
433
+        if (version_compare($mimeTypeVersion, '20.0.0.5', '<') && $this->introduceOpenDocumentTemplates()) {
434
+            $output->info('Fixed OpenDocument template mime types');
435
+        }
436
+
437
+        if (version_compare($mimeTypeVersion, '21.0.0.7', '<') && $this->introduceOrgModeType()) {
438
+            $output->info('Fixed orgmode mime types');
439
+        }
440
+
441
+        if (version_compare($mimeTypeVersion, '23.0.0.2', '<') && $this->introduceFlatOpenDocumentType()) {
442
+            $output->info('Fixed Flat OpenDocument mime types');
443
+        }
444
+
445
+        if (version_compare($mimeTypeVersion, '25.0.0.2', '<') && $this->introduceOnlyofficeFormType()) {
446
+            $output->info('Fixed ONLYOFFICE Forms OpenXML mime types');
447
+        }
448
+
449
+        if (version_compare($mimeTypeVersion, '26.0.0.1', '<') && $this->introduceAsciidocType()) {
450
+            $output->info('Fixed AsciiDoc mime types');
451
+        }
452
+
453
+        if (version_compare($mimeTypeVersion, '28.0.0.5', '<') && $this->introduceEnhancedMetafileFormatType()) {
454
+            $output->info('Fixed Enhanced Metafile Format mime types');
455
+        }
456
+
457
+        if (version_compare($mimeTypeVersion, '29.0.0.2', '<') && $this->introduceEmlAndMsgFormatType()) {
458
+            $output->info('Fixed eml and msg mime type');
459
+        }
460
+
461
+        if (version_compare($mimeTypeVersion, '29.0.0.6', '<') && $this->introduceAacAudioType()) {
462
+            $output->info('Fixed aac mime type');
463
+        }
464
+
465
+        if (version_compare($mimeTypeVersion, '29.0.0.10', '<') && $this->introduceReStructuredTextFormatType()) {
466
+            $output->info('Fixed ReStructured Text mime type');
467
+        }
468
+
469
+        if (version_compare($mimeTypeVersion, '30.0.0.0', '<') && $this->introduceExcalidrawType()) {
470
+            $output->info('Fixed Excalidraw mime type');
471
+        }
472
+
473
+        if (version_compare($mimeTypeVersion, '31.0.0.0', '<') && $this->introduceZstType()) {
474
+            $output->info('Fixed zst mime type');
475
+        }
476
+
477
+        if (version_compare($mimeTypeVersion, '32.0.0.0', '<') && $this->introduceMusicxmlType()) {
478
+            $output->info('Fixed musicxml mime type');
479
+        }
480
+
481
+        if (version_compare($mimeTypeVersion, '32.0.0.0', '<') && $this->introduceTextType()) {
482
+            $out->info('Fixed text mime type');
483
+        }
484
+
485
+        if (!$this->dryRun) {
486
+            $this->appConfig->setValueString('files', 'mimetype_version', $serverVersion);
487
+        }
488
+    }
489 489
 }
Please login to merge, or discard this patch.
apps/dav/lib/Migration/BuildSocialSearchIndexBackgroundJob.php 2 patches
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -17,72 +17,72 @@
 block discarded – undo
17 17
 use Psr\Log\LoggerInterface;
18 18
 
19 19
 class BuildSocialSearchIndexBackgroundJob extends QueuedJob {
20
-	public function __construct(
21
-		private IDBConnection $db,
22
-		private CardDavBackend $davBackend,
23
-		private LoggerInterface $logger,
24
-		private IJobList $jobList,
25
-		ITimeFactory $timeFactory,
26
-	) {
27
-		parent::__construct($timeFactory);
28
-	}
20
+    public function __construct(
21
+        private IDBConnection $db,
22
+        private CardDavBackend $davBackend,
23
+        private LoggerInterface $logger,
24
+        private IJobList $jobList,
25
+        ITimeFactory $timeFactory,
26
+    ) {
27
+        parent::__construct($timeFactory);
28
+    }
29 29
 
30
-	public function run($argument) {
31
-		$offset = $argument['offset'];
32
-		$stopAt = $argument['stopAt'];
30
+    public function run($argument) {
31
+        $offset = $argument['offset'];
32
+        $stopAt = $argument['stopAt'];
33 33
 
34
-		$this->logger->info('Indexing social profile data (' . $offset . '/' . $stopAt . ')');
34
+        $this->logger->info('Indexing social profile data (' . $offset . '/' . $stopAt . ')');
35 35
 
36
-		$offset = $this->buildIndex($offset, $stopAt);
36
+        $offset = $this->buildIndex($offset, $stopAt);
37 37
 
38
-		if ($offset >= $stopAt) {
39
-			$this->logger->info('All contacts with social profiles indexed');
40
-		} else {
41
-			$this->jobList->add(self::class, [
42
-				'offset' => $offset,
43
-				'stopAt' => $stopAt
44
-			]);
45
-			$this->logger->info('New social profile indexing job scheduled with offset ' . $offset);
46
-		}
47
-	}
38
+        if ($offset >= $stopAt) {
39
+            $this->logger->info('All contacts with social profiles indexed');
40
+        } else {
41
+            $this->jobList->add(self::class, [
42
+                'offset' => $offset,
43
+                'stopAt' => $stopAt
44
+            ]);
45
+            $this->logger->info('New social profile indexing job scheduled with offset ' . $offset);
46
+        }
47
+    }
48 48
 
49
-	/**
50
-	 * @param int $offset
51
-	 * @param int $stopAt
52
-	 * @return int
53
-	 */
54
-	private function buildIndex($offset, $stopAt) {
55
-		$startTime = $this->time->getTime();
49
+    /**
50
+     * @param int $offset
51
+     * @param int $stopAt
52
+     * @return int
53
+     */
54
+    private function buildIndex($offset, $stopAt) {
55
+        $startTime = $this->time->getTime();
56 56
 
57
-		// get contacts with social profiles
58
-		$query = $this->db->getQueryBuilder();
59
-		$query->select('id', 'addressbookid', 'uri', 'carddata')
60
-			->from('cards', 'c')
61
-			->orderBy('id', 'ASC')
62
-			->where($query->expr()->like('carddata', $query->createNamedParameter('%SOCIALPROFILE%')))
63
-			->andWhere($query->expr()->gt('id', $query->createNamedParameter((int)$offset, IQueryBuilder::PARAM_INT)))
64
-			->setMaxResults(100);
65
-		$social_cards = $query->executeQuery()->fetchAll();
57
+        // get contacts with social profiles
58
+        $query = $this->db->getQueryBuilder();
59
+        $query->select('id', 'addressbookid', 'uri', 'carddata')
60
+            ->from('cards', 'c')
61
+            ->orderBy('id', 'ASC')
62
+            ->where($query->expr()->like('carddata', $query->createNamedParameter('%SOCIALPROFILE%')))
63
+            ->andWhere($query->expr()->gt('id', $query->createNamedParameter((int)$offset, IQueryBuilder::PARAM_INT)))
64
+            ->setMaxResults(100);
65
+        $social_cards = $query->executeQuery()->fetchAll();
66 66
 
67
-		if (empty($social_cards)) {
68
-			return $stopAt;
69
-		}
67
+        if (empty($social_cards)) {
68
+            return $stopAt;
69
+        }
70 70
 
71
-		// refresh identified contacts in order to re-index
72
-		foreach ($social_cards as $contact) {
73
-			$offset = $contact['id'];
74
-			$cardData = $contact['carddata'];
75
-			if (is_resource($cardData) && (get_resource_type($cardData) === 'stream')) {
76
-				$cardData = stream_get_contents($cardData);
77
-			}
78
-			$this->davBackend->updateCard($contact['addressbookid'], $contact['uri'], $cardData);
71
+        // refresh identified contacts in order to re-index
72
+        foreach ($social_cards as $contact) {
73
+            $offset = $contact['id'];
74
+            $cardData = $contact['carddata'];
75
+            if (is_resource($cardData) && (get_resource_type($cardData) === 'stream')) {
76
+                $cardData = stream_get_contents($cardData);
77
+            }
78
+            $this->davBackend->updateCard($contact['addressbookid'], $contact['uri'], $cardData);
79 79
 
80
-			// stop after 15sec (to be continued with next chunk)
81
-			if (($this->time->getTime() - $startTime) > 15) {
82
-				break;
83
-			}
84
-		}
80
+            // stop after 15sec (to be continued with next chunk)
81
+            if (($this->time->getTime() - $startTime) > 15) {
82
+                break;
83
+            }
84
+        }
85 85
 
86
-		return $offset;
87
-	}
86
+        return $offset;
87
+    }
88 88
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
 		$offset = $argument['offset'];
32 32
 		$stopAt = $argument['stopAt'];
33 33
 
34
-		$this->logger->info('Indexing social profile data (' . $offset . '/' . $stopAt . ')');
34
+		$this->logger->info('Indexing social profile data ('.$offset.'/'.$stopAt.')');
35 35
 
36 36
 		$offset = $this->buildIndex($offset, $stopAt);
37 37
 
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
 				'offset' => $offset,
43 43
 				'stopAt' => $stopAt
44 44
 			]);
45
-			$this->logger->info('New social profile indexing job scheduled with offset ' . $offset);
45
+			$this->logger->info('New social profile indexing job scheduled with offset '.$offset);
46 46
 		}
47 47
 	}
48 48
 
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
 			->from('cards', 'c')
61 61
 			->orderBy('id', 'ASC')
62 62
 			->where($query->expr()->like('carddata', $query->createNamedParameter('%SOCIALPROFILE%')))
63
-			->andWhere($query->expr()->gt('id', $query->createNamedParameter((int)$offset, IQueryBuilder::PARAM_INT)))
63
+			->andWhere($query->expr()->gt('id', $query->createNamedParameter((int) $offset, IQueryBuilder::PARAM_INT)))
64 64
 			->setMaxResults(100);
65 65
 		$social_cards = $query->executeQuery()->fetchAll();
66 66
 
Please login to merge, or discard this patch.
apps/dav/lib/Migration/BuildCalendarSearchIndexBackgroundJob.php 2 patches
Indentation   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -16,67 +16,67 @@
 block discarded – undo
16 16
 use Psr\Log\LoggerInterface;
17 17
 
18 18
 class BuildCalendarSearchIndexBackgroundJob extends QueuedJob {
19
-	public function __construct(
20
-		private IDBConnection $db,
21
-		private CalDavBackend $calDavBackend,
22
-		private LoggerInterface $logger,
23
-		private IJobList $jobList,
24
-		ITimeFactory $timeFactory,
25
-	) {
26
-		parent::__construct($timeFactory);
27
-	}
19
+    public function __construct(
20
+        private IDBConnection $db,
21
+        private CalDavBackend $calDavBackend,
22
+        private LoggerInterface $logger,
23
+        private IJobList $jobList,
24
+        ITimeFactory $timeFactory,
25
+    ) {
26
+        parent::__construct($timeFactory);
27
+    }
28 28
 
29
-	public function run($argument) {
30
-		$offset = (int)$argument['offset'];
31
-		$stopAt = (int)$argument['stopAt'];
29
+    public function run($argument) {
30
+        $offset = (int)$argument['offset'];
31
+        $stopAt = (int)$argument['stopAt'];
32 32
 
33
-		$this->logger->info('Building calendar index (' . $offset . '/' . $stopAt . ')');
33
+        $this->logger->info('Building calendar index (' . $offset . '/' . $stopAt . ')');
34 34
 
35
-		$startTime = $this->time->getTime();
36
-		while (($this->time->getTime() - $startTime) < 15) {
37
-			$offset = $this->buildIndex($offset, $stopAt);
38
-			if ($offset >= $stopAt) {
39
-				break;
40
-			}
41
-		}
35
+        $startTime = $this->time->getTime();
36
+        while (($this->time->getTime() - $startTime) < 15) {
37
+            $offset = $this->buildIndex($offset, $stopAt);
38
+            if ($offset >= $stopAt) {
39
+                break;
40
+            }
41
+        }
42 42
 
43
-		if ($offset >= $stopAt) {
44
-			$this->logger->info('Building calendar index done');
45
-		} else {
46
-			$this->jobList->add(self::class, [
47
-				'offset' => $offset,
48
-				'stopAt' => $stopAt
49
-			]);
50
-			$this->logger->info('New building calendar index job scheduled with offset ' . $offset);
51
-		}
52
-	}
43
+        if ($offset >= $stopAt) {
44
+            $this->logger->info('Building calendar index done');
45
+        } else {
46
+            $this->jobList->add(self::class, [
47
+                'offset' => $offset,
48
+                'stopAt' => $stopAt
49
+            ]);
50
+            $this->logger->info('New building calendar index job scheduled with offset ' . $offset);
51
+        }
52
+    }
53 53
 
54
-	/**
55
-	 * @param int $offset
56
-	 * @param int $stopAt
57
-	 * @return int
58
-	 */
59
-	private function buildIndex(int $offset, int $stopAt): int {
60
-		$query = $this->db->getQueryBuilder();
61
-		$query->select(['id', 'calendarid', 'uri', 'calendardata'])
62
-			->from('calendarobjects')
63
-			->where($query->expr()->lte('id', $query->createNamedParameter($stopAt)))
64
-			->andWhere($query->expr()->gt('id', $query->createNamedParameter($offset)))
65
-			->orderBy('id', 'ASC')
66
-			->setMaxResults(500);
54
+    /**
55
+     * @param int $offset
56
+     * @param int $stopAt
57
+     * @return int
58
+     */
59
+    private function buildIndex(int $offset, int $stopAt): int {
60
+        $query = $this->db->getQueryBuilder();
61
+        $query->select(['id', 'calendarid', 'uri', 'calendardata'])
62
+            ->from('calendarobjects')
63
+            ->where($query->expr()->lte('id', $query->createNamedParameter($stopAt)))
64
+            ->andWhere($query->expr()->gt('id', $query->createNamedParameter($offset)))
65
+            ->orderBy('id', 'ASC')
66
+            ->setMaxResults(500);
67 67
 
68
-		$result = $query->executeQuery();
69
-		while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
70
-			$offset = $row['id'];
68
+        $result = $query->executeQuery();
69
+        while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
70
+            $offset = $row['id'];
71 71
 
72
-			$calendarData = $row['calendardata'];
73
-			if (is_resource($calendarData)) {
74
-				$calendarData = stream_get_contents($calendarData);
75
-			}
72
+            $calendarData = $row['calendardata'];
73
+            if (is_resource($calendarData)) {
74
+                $calendarData = stream_get_contents($calendarData);
75
+            }
76 76
 
77
-			$this->calDavBackend->updateProperties($row['calendarid'], $row['uri'], $calendarData);
78
-		}
77
+            $this->calDavBackend->updateProperties($row['calendarid'], $row['uri'], $calendarData);
78
+        }
79 79
 
80
-		return $offset;
81
-	}
80
+        return $offset;
81
+    }
82 82
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -27,10 +27,10 @@  discard block
 block discarded – undo
27 27
 	}
28 28
 
29 29
 	public function run($argument) {
30
-		$offset = (int)$argument['offset'];
31
-		$stopAt = (int)$argument['stopAt'];
30
+		$offset = (int) $argument['offset'];
31
+		$stopAt = (int) $argument['stopAt'];
32 32
 
33
-		$this->logger->info('Building calendar index (' . $offset . '/' . $stopAt . ')');
33
+		$this->logger->info('Building calendar index ('.$offset.'/'.$stopAt.')');
34 34
 
35 35
 		$startTime = $this->time->getTime();
36 36
 		while (($this->time->getTime() - $startTime) < 15) {
@@ -47,7 +47,7 @@  discard block
 block discarded – undo
47 47
 				'offset' => $offset,
48 48
 				'stopAt' => $stopAt
49 49
 			]);
50
-			$this->logger->info('New building calendar index job scheduled with offset ' . $offset);
50
+			$this->logger->info('New building calendar index job scheduled with offset '.$offset);
51 51
 		}
52 52
 	}
53 53
 
Please login to merge, or discard this patch.
core/BackgroundJobs/CheckForUserCertificates.php 2 patches
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -18,43 +18,43 @@
 block discarded – undo
18 18
 use OCP\IUserManager;
19 19
 
20 20
 class CheckForUserCertificates extends QueuedJob {
21
-	public function __construct(
22
-		protected IConfig $config,
23
-		private IUserManager $userManager,
24
-		private IRootFolder $rootFolder,
25
-		ITimeFactory $time,
26
-	) {
27
-		parent::__construct($time);
28
-	}
21
+    public function __construct(
22
+        protected IConfig $config,
23
+        private IUserManager $userManager,
24
+        private IRootFolder $rootFolder,
25
+        ITimeFactory $time,
26
+    ) {
27
+        parent::__construct($time);
28
+    }
29 29
 
30
-	/**
31
-	 * Checks all user directories for old user uploaded certificates
32
-	 */
33
-	public function run($argument): void {
34
-		$uploadList = [];
35
-		$this->userManager->callForSeenUsers(function (IUser $user) use (&$uploadList): void {
36
-			$userId = $user->getUID();
37
-			try {
38
-				\OC_Util::setupFS($userId);
39
-				$filesExternalUploadsFolder = $this->rootFolder->get($userId . '/files_external/uploads');
40
-			} catch (NotFoundException $e) {
41
-				\OC_Util::tearDownFS();
42
-				return;
43
-			}
44
-			if ($filesExternalUploadsFolder instanceof Folder) {
45
-				$files = $filesExternalUploadsFolder->getDirectoryListing();
46
-				foreach ($files as $file) {
47
-					$filename = $file->getName();
48
-					$uploadList[] = "$userId/files_external/uploads/$filename";
49
-				}
50
-			}
51
-			\OC_Util::tearDownFS();
52
-		});
30
+    /**
31
+     * Checks all user directories for old user uploaded certificates
32
+     */
33
+    public function run($argument): void {
34
+        $uploadList = [];
35
+        $this->userManager->callForSeenUsers(function (IUser $user) use (&$uploadList): void {
36
+            $userId = $user->getUID();
37
+            try {
38
+                \OC_Util::setupFS($userId);
39
+                $filesExternalUploadsFolder = $this->rootFolder->get($userId . '/files_external/uploads');
40
+            } catch (NotFoundException $e) {
41
+                \OC_Util::tearDownFS();
42
+                return;
43
+            }
44
+            if ($filesExternalUploadsFolder instanceof Folder) {
45
+                $files = $filesExternalUploadsFolder->getDirectoryListing();
46
+                foreach ($files as $file) {
47
+                    $filename = $file->getName();
48
+                    $uploadList[] = "$userId/files_external/uploads/$filename";
49
+                }
50
+            }
51
+            \OC_Util::tearDownFS();
52
+        });
53 53
 
54
-		if (empty($uploadList)) {
55
-			$this->config->deleteAppValue('files_external', 'user_certificate_scan');
56
-		} else {
57
-			$this->config->setAppValue('files_external', 'user_certificate_scan', json_encode($uploadList));
58
-		}
59
-	}
54
+        if (empty($uploadList)) {
55
+            $this->config->deleteAppValue('files_external', 'user_certificate_scan');
56
+        } else {
57
+            $this->config->setAppValue('files_external', 'user_certificate_scan', json_encode($uploadList));
58
+        }
59
+    }
60 60
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -32,11 +32,11 @@
 block discarded – undo
32 32
 	 */
33 33
 	public function run($argument): void {
34 34
 		$uploadList = [];
35
-		$this->userManager->callForSeenUsers(function (IUser $user) use (&$uploadList): void {
35
+		$this->userManager->callForSeenUsers(function(IUser $user) use (&$uploadList): void {
36 36
 			$userId = $user->getUID();
37 37
 			try {
38 38
 				\OC_Util::setupFS($userId);
39
-				$filesExternalUploadsFolder = $this->rootFolder->get($userId . '/files_external/uploads');
39
+				$filesExternalUploadsFolder = $this->rootFolder->get($userId.'/files_external/uploads');
40 40
 			} catch (NotFoundException $e) {
41 41
 				\OC_Util::tearDownFS();
42 42
 				return;
Please login to merge, or discard this patch.