Completed
Pull Request — master (#5424)
by Robin
15:50
created
lib/private/Files/Cache/Wrapper/CacheJail.php 1 patch
Indentation   +262 added lines, -262 removed lines patch added patch discarded remove patch
@@ -34,294 +34,294 @@
 block discarded – undo
34 34
  * Jail to a subdirectory of the wrapped cache
35 35
  */
36 36
 class CacheJail extends CacheWrapper {
37
-	/**
38
-	 * @var string
39
-	 */
40
-	protected $root;
37
+    /**
38
+     * @var string
39
+     */
40
+    protected $root;
41 41
 
42
-	/**
43
-	 * @param \OCP\Files\Cache\ICache $cache
44
-	 * @param string $root
45
-	 */
46
-	public function __construct($cache, $root) {
47
-		parent::__construct($cache);
48
-		$this->root = $root;
49
-	}
42
+    /**
43
+     * @param \OCP\Files\Cache\ICache $cache
44
+     * @param string $root
45
+     */
46
+    public function __construct($cache, $root) {
47
+        parent::__construct($cache);
48
+        $this->root = $root;
49
+    }
50 50
 
51
-	protected function getSourcePath($path) {
52
-		if ($path === '') {
53
-			return $this->root;
54
-		} else {
55
-			return $this->root . '/' . ltrim($path, '/');
56
-		}
57
-	}
51
+    protected function getSourcePath($path) {
52
+        if ($path === '') {
53
+            return $this->root;
54
+        } else {
55
+            return $this->root . '/' . ltrim($path, '/');
56
+        }
57
+    }
58 58
 
59
-	/**
60
-	 * @param string $path
61
-	 * @return null|string the jailed path or null if the path is outside the jail
62
-	 */
63
-	protected function getJailedPath($path) {
64
-		if ($this->root === '') {
65
-			return $path;
66
-		}
67
-		$rootLength = strlen($this->root) + 1;
68
-		if ($path === $this->root) {
69
-			return '';
70
-		} else if (substr($path, 0, $rootLength) === $this->root . '/') {
71
-			return substr($path, $rootLength);
72
-		} else {
73
-			return null;
74
-		}
75
-	}
59
+    /**
60
+     * @param string $path
61
+     * @return null|string the jailed path or null if the path is outside the jail
62
+     */
63
+    protected function getJailedPath($path) {
64
+        if ($this->root === '') {
65
+            return $path;
66
+        }
67
+        $rootLength = strlen($this->root) + 1;
68
+        if ($path === $this->root) {
69
+            return '';
70
+        } else if (substr($path, 0, $rootLength) === $this->root . '/') {
71
+            return substr($path, $rootLength);
72
+        } else {
73
+            return null;
74
+        }
75
+    }
76 76
 
77
-	/**
78
-	 * @param ICacheEntry|array $entry
79
-	 * @return array
80
-	 */
81
-	protected function formatCacheEntry($entry) {
82
-		if (isset($entry['path'])) {
83
-			$entry['path'] = $this->getJailedPath($entry['path']);
84
-		}
85
-		return $entry;
86
-	}
77
+    /**
78
+     * @param ICacheEntry|array $entry
79
+     * @return array
80
+     */
81
+    protected function formatCacheEntry($entry) {
82
+        if (isset($entry['path'])) {
83
+            $entry['path'] = $this->getJailedPath($entry['path']);
84
+        }
85
+        return $entry;
86
+    }
87 87
 
88
-	protected function filterCacheEntry($entry) {
89
-		$rootLength = strlen($this->root) + 1;
90
-		return ($entry['path'] === $this->root) or (substr($entry['path'], 0, $rootLength) === $this->root . '/');
91
-	}
88
+    protected function filterCacheEntry($entry) {
89
+        $rootLength = strlen($this->root) + 1;
90
+        return ($entry['path'] === $this->root) or (substr($entry['path'], 0, $rootLength) === $this->root . '/');
91
+    }
92 92
 
93
-	/**
94
-	 * get the stored metadata of a file or folder
95
-	 *
96
-	 * @param string /int $file
97
-	 * @return ICacheEntry|false
98
-	 */
99
-	public function get($file) {
100
-		if (is_string($file) or $file == '') {
101
-			$file = $this->getSourcePath($file);
102
-		}
103
-		return parent::get($file);
104
-	}
93
+    /**
94
+     * get the stored metadata of a file or folder
95
+     *
96
+     * @param string /int $file
97
+     * @return ICacheEntry|false
98
+     */
99
+    public function get($file) {
100
+        if (is_string($file) or $file == '') {
101
+            $file = $this->getSourcePath($file);
102
+        }
103
+        return parent::get($file);
104
+    }
105 105
 
106
-	/**
107
-	 * insert meta data for a new file or folder
108
-	 *
109
-	 * @param string $file
110
-	 * @param array $data
111
-	 *
112
-	 * @return int file id
113
-	 * @throws \RuntimeException
114
-	 */
115
-	public function insert($file, array $data) {
116
-		return $this->getCache()->insert($this->getSourcePath($file), $data);
117
-	}
106
+    /**
107
+     * insert meta data for a new file or folder
108
+     *
109
+     * @param string $file
110
+     * @param array $data
111
+     *
112
+     * @return int file id
113
+     * @throws \RuntimeException
114
+     */
115
+    public function insert($file, array $data) {
116
+        return $this->getCache()->insert($this->getSourcePath($file), $data);
117
+    }
118 118
 
119
-	/**
120
-	 * update the metadata in the cache
121
-	 *
122
-	 * @param int $id
123
-	 * @param array $data
124
-	 */
125
-	public function update($id, array $data) {
126
-		$this->getCache()->update($id, $data);
127
-	}
119
+    /**
120
+     * update the metadata in the cache
121
+     *
122
+     * @param int $id
123
+     * @param array $data
124
+     */
125
+    public function update($id, array $data) {
126
+        $this->getCache()->update($id, $data);
127
+    }
128 128
 
129
-	/**
130
-	 * get the file id for a file
131
-	 *
132
-	 * @param string $file
133
-	 * @return int
134
-	 */
135
-	public function getId($file) {
136
-		return $this->getCache()->getId($this->getSourcePath($file));
137
-	}
129
+    /**
130
+     * get the file id for a file
131
+     *
132
+     * @param string $file
133
+     * @return int
134
+     */
135
+    public function getId($file) {
136
+        return $this->getCache()->getId($this->getSourcePath($file));
137
+    }
138 138
 
139
-	/**
140
-	 * get the id of the parent folder of a file
141
-	 *
142
-	 * @param string $file
143
-	 * @return int
144
-	 */
145
-	public function getParentId($file) {
146
-		return $this->getCache()->getParentId($this->getSourcePath($file));
147
-	}
139
+    /**
140
+     * get the id of the parent folder of a file
141
+     *
142
+     * @param string $file
143
+     * @return int
144
+     */
145
+    public function getParentId($file) {
146
+        return $this->getCache()->getParentId($this->getSourcePath($file));
147
+    }
148 148
 
149
-	/**
150
-	 * check if a file is available in the cache
151
-	 *
152
-	 * @param string $file
153
-	 * @return bool
154
-	 */
155
-	public function inCache($file) {
156
-		return $this->getCache()->inCache($this->getSourcePath($file));
157
-	}
149
+    /**
150
+     * check if a file is available in the cache
151
+     *
152
+     * @param string $file
153
+     * @return bool
154
+     */
155
+    public function inCache($file) {
156
+        return $this->getCache()->inCache($this->getSourcePath($file));
157
+    }
158 158
 
159
-	/**
160
-	 * remove a file or folder from the cache
161
-	 *
162
-	 * @param string $file
163
-	 */
164
-	public function remove($file) {
165
-		$this->getCache()->remove($this->getSourcePath($file));
166
-	}
159
+    /**
160
+     * remove a file or folder from the cache
161
+     *
162
+     * @param string $file
163
+     */
164
+    public function remove($file) {
165
+        $this->getCache()->remove($this->getSourcePath($file));
166
+    }
167 167
 
168
-	/**
169
-	 * Move a file or folder in the cache
170
-	 *
171
-	 * @param string $source
172
-	 * @param string $target
173
-	 */
174
-	public function move($source, $target) {
175
-		$this->getCache()->move($this->getSourcePath($source), $this->getSourcePath($target));
176
-	}
168
+    /**
169
+     * Move a file or folder in the cache
170
+     *
171
+     * @param string $source
172
+     * @param string $target
173
+     */
174
+    public function move($source, $target) {
175
+        $this->getCache()->move($this->getSourcePath($source), $this->getSourcePath($target));
176
+    }
177 177
 
178
-	/**
179
-	 * Get the storage id and path needed for a move
180
-	 *
181
-	 * @param string $path
182
-	 * @return array [$storageId, $internalPath]
183
-	 */
184
-	protected function getMoveInfo($path) {
185
-		return [$this->getNumericStorageId(), $this->getSourcePath($path)];
186
-	}
178
+    /**
179
+     * Get the storage id and path needed for a move
180
+     *
181
+     * @param string $path
182
+     * @return array [$storageId, $internalPath]
183
+     */
184
+    protected function getMoveInfo($path) {
185
+        return [$this->getNumericStorageId(), $this->getSourcePath($path)];
186
+    }
187 187
 
188
-	/**
189
-	 * remove all entries for files that are stored on the storage from the cache
190
-	 */
191
-	public function clear() {
192
-		$this->getCache()->remove($this->root);
193
-	}
188
+    /**
189
+     * remove all entries for files that are stored on the storage from the cache
190
+     */
191
+    public function clear() {
192
+        $this->getCache()->remove($this->root);
193
+    }
194 194
 
195
-	/**
196
-	 * @param string $file
197
-	 *
198
-	 * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
199
-	 */
200
-	public function getStatus($file) {
201
-		return $this->getCache()->getStatus($this->getSourcePath($file));
202
-	}
195
+    /**
196
+     * @param string $file
197
+     *
198
+     * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
199
+     */
200
+    public function getStatus($file) {
201
+        return $this->getCache()->getStatus($this->getSourcePath($file));
202
+    }
203 203
 
204
-	private function formatSearchResults($results) {
205
-		$results = array_filter($results, array($this, 'filterCacheEntry'));
206
-		$results = array_values($results);
207
-		return array_map(array($this, 'formatCacheEntry'), $results);
208
-	}
204
+    private function formatSearchResults($results) {
205
+        $results = array_filter($results, array($this, 'filterCacheEntry'));
206
+        $results = array_values($results);
207
+        return array_map(array($this, 'formatCacheEntry'), $results);
208
+    }
209 209
 
210
-	/**
211
-	 * search for files matching $pattern
212
-	 *
213
-	 * @param string $pattern
214
-	 * @return array an array of file data
215
-	 */
216
-	public function search($pattern) {
217
-		$results = $this->getCache()->search($pattern);
218
-		return $this->formatSearchResults($results);
219
-	}
210
+    /**
211
+     * search for files matching $pattern
212
+     *
213
+     * @param string $pattern
214
+     * @return array an array of file data
215
+     */
216
+    public function search($pattern) {
217
+        $results = $this->getCache()->search($pattern);
218
+        return $this->formatSearchResults($results);
219
+    }
220 220
 
221
-	/**
222
-	 * search for files by mimetype
223
-	 *
224
-	 * @param string $mimetype
225
-	 * @return array
226
-	 */
227
-	public function searchByMime($mimetype) {
228
-		$results = $this->getCache()->searchByMime($mimetype);
229
-		return $this->formatSearchResults($results);
230
-	}
221
+    /**
222
+     * search for files by mimetype
223
+     *
224
+     * @param string $mimetype
225
+     * @return array
226
+     */
227
+    public function searchByMime($mimetype) {
228
+        $results = $this->getCache()->searchByMime($mimetype);
229
+        return $this->formatSearchResults($results);
230
+    }
231 231
 
232
-	public function searchQuery(ISearchQuery $query) {
233
-		$results = $this->getCache()->searchQuery($query);
234
-		return $this->formatSearchResults($results);
235
-	}
232
+    public function searchQuery(ISearchQuery $query) {
233
+        $results = $this->getCache()->searchQuery($query);
234
+        return $this->formatSearchResults($results);
235
+    }
236 236
 
237
-	/**
238
-	 * search for files by mimetype
239
-	 *
240
-	 * @param string|int $tag name or tag id
241
-	 * @param string $userId owner of the tags
242
-	 * @return array
243
-	 */
244
-	public function searchByTag($tag, $userId) {
245
-		$results = $this->getCache()->searchByTag($tag, $userId);
246
-		return $this->formatSearchResults($results);
247
-	}
237
+    /**
238
+     * search for files by mimetype
239
+     *
240
+     * @param string|int $tag name or tag id
241
+     * @param string $userId owner of the tags
242
+     * @return array
243
+     */
244
+    public function searchByTag($tag, $userId) {
245
+        $results = $this->getCache()->searchByTag($tag, $userId);
246
+        return $this->formatSearchResults($results);
247
+    }
248 248
 
249
-	/**
250
-	 * update the folder size and the size of all parent folders
251
-	 *
252
-	 * @param string|boolean $path
253
-	 * @param array $data (optional) meta data of the folder
254
-	 */
255
-	public function correctFolderSize($path, $data = null) {
256
-		if ($this->getCache() instanceof Cache) {
257
-			$this->getCache()->correctFolderSize($this->getSourcePath($path), $data);
258
-		}
259
-	}
249
+    /**
250
+     * update the folder size and the size of all parent folders
251
+     *
252
+     * @param string|boolean $path
253
+     * @param array $data (optional) meta data of the folder
254
+     */
255
+    public function correctFolderSize($path, $data = null) {
256
+        if ($this->getCache() instanceof Cache) {
257
+            $this->getCache()->correctFolderSize($this->getSourcePath($path), $data);
258
+        }
259
+    }
260 260
 
261
-	/**
262
-	 * get the size of a folder and set it in the cache
263
-	 *
264
-	 * @param string $path
265
-	 * @param array $entry (optional) meta data of the folder
266
-	 * @return int
267
-	 */
268
-	public function calculateFolderSize($path, $entry = null) {
269
-		if ($this->getCache() instanceof Cache) {
270
-			return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry);
271
-		} else {
272
-			return 0;
273
-		}
261
+    /**
262
+     * get the size of a folder and set it in the cache
263
+     *
264
+     * @param string $path
265
+     * @param array $entry (optional) meta data of the folder
266
+     * @return int
267
+     */
268
+    public function calculateFolderSize($path, $entry = null) {
269
+        if ($this->getCache() instanceof Cache) {
270
+            return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry);
271
+        } else {
272
+            return 0;
273
+        }
274 274
 
275
-	}
275
+    }
276 276
 
277
-	/**
278
-	 * get all file ids on the files on the storage
279
-	 *
280
-	 * @return int[]
281
-	 */
282
-	public function getAll() {
283
-		// not supported
284
-		return array();
285
-	}
277
+    /**
278
+     * get all file ids on the files on the storage
279
+     *
280
+     * @return int[]
281
+     */
282
+    public function getAll() {
283
+        // not supported
284
+        return array();
285
+    }
286 286
 
287
-	/**
288
-	 * find a folder in the cache which has not been fully scanned
289
-	 *
290
-	 * If multiply incomplete folders are in the cache, the one with the highest id will be returned,
291
-	 * use the one with the highest id gives the best result with the background scanner, since that is most
292
-	 * likely the folder where we stopped scanning previously
293
-	 *
294
-	 * @return string|bool the path of the folder or false when no folder matched
295
-	 */
296
-	public function getIncomplete() {
297
-		// not supported
298
-		return false;
299
-	}
287
+    /**
288
+     * find a folder in the cache which has not been fully scanned
289
+     *
290
+     * If multiply incomplete folders are in the cache, the one with the highest id will be returned,
291
+     * use the one with the highest id gives the best result with the background scanner, since that is most
292
+     * likely the folder where we stopped scanning previously
293
+     *
294
+     * @return string|bool the path of the folder or false when no folder matched
295
+     */
296
+    public function getIncomplete() {
297
+        // not supported
298
+        return false;
299
+    }
300 300
 
301
-	/**
302
-	 * get the path of a file on this storage by it's id
303
-	 *
304
-	 * @param int $id
305
-	 * @return string|null
306
-	 */
307
-	public function getPathById($id) {
308
-		$path = $this->getCache()->getPathById($id);
309
-		return $this->getJailedPath($path);
310
-	}
301
+    /**
302
+     * get the path of a file on this storage by it's id
303
+     *
304
+     * @param int $id
305
+     * @return string|null
306
+     */
307
+    public function getPathById($id) {
308
+        $path = $this->getCache()->getPathById($id);
309
+        return $this->getJailedPath($path);
310
+    }
311 311
 
312
-	/**
313
-	 * Move a file or folder in the cache
314
-	 *
315
-	 * Note that this should make sure the entries are removed from the source cache
316
-	 *
317
-	 * @param \OCP\Files\Cache\ICache $sourceCache
318
-	 * @param string $sourcePath
319
-	 * @param string $targetPath
320
-	 */
321
-	public function moveFromCache(\OCP\Files\Cache\ICache $sourceCache, $sourcePath, $targetPath) {
322
-		if ($sourceCache === $this) {
323
-			return $this->move($sourcePath, $targetPath);
324
-		}
325
-		return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath));
326
-	}
312
+    /**
313
+     * Move a file or folder in the cache
314
+     *
315
+     * Note that this should make sure the entries are removed from the source cache
316
+     *
317
+     * @param \OCP\Files\Cache\ICache $sourceCache
318
+     * @param string $sourcePath
319
+     * @param string $targetPath
320
+     */
321
+    public function moveFromCache(\OCP\Files\Cache\ICache $sourceCache, $sourcePath, $targetPath) {
322
+        if ($sourceCache === $this) {
323
+            return $this->move($sourcePath, $targetPath);
324
+        }
325
+        return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath));
326
+    }
327 327
 }
Please login to merge, or discard this patch.
lib/private/Repair/RepairInvalidPaths.php 3 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -101,7 +101,7 @@  discard block
 block discarded – undo
101 101
 	private function repair() {
102 102
 		$entries = $this->getInvalidEntries();
103 103
 		foreach ($entries as $entry) {
104
-			$calculatedPath = $entry['parent_path'] . '/' . $entry['name'];
104
+			$calculatedPath = $entry['parent_path'].'/'.$entry['name'];
105 105
 			if ($newId = $this->getId($entry['storage'], $calculatedPath)) {
106 106
 				// a new entry with the correct path has already been created, reuse that one and delete the incorrect entry
107 107
 				$this->reparent($entry['fileid'], $newId);
@@ -116,6 +116,6 @@  discard block
 block discarded – undo
116 116
 	public function run(IOutput $output) {
117 117
 		$count = $this->repair();
118 118
 
119
-		$output->info('Repaired ' . $count . ' paths');
119
+		$output->info('Repaired '.$count.' paths');
120 120
 	}
121 121
 }
Please login to merge, or discard this patch.
Doc Comments   +6 added lines patch added patch discarded remove patch
@@ -59,6 +59,9 @@  discard block
 block discarded – undo
59 59
 		return $query->execute()->fetchAll();
60 60
 	}
61 61
 
62
+	/**
63
+	 * @param string $path
64
+	 */
62 65
 	private function getId($storage, $path) {
63 66
 		$builder = $this->connection->getQueryBuilder();
64 67
 
@@ -70,6 +73,9 @@  discard block
 block discarded – undo
70 73
 		return $query->execute()->fetchColumn();
71 74
 	}
72 75
 
76
+	/**
77
+	 * @param string $newPath
78
+	 */
73 79
 	private function update($fileid, $newPath) {
74 80
 		$builder = $this->connection->getQueryBuilder();
75 81
 
Please login to merge, or discard this patch.
Indentation   +91 added lines, -91 removed lines patch added patch discarded remove patch
@@ -27,95 +27,95 @@
 block discarded – undo
27 27
 use OCP\Migration\IRepairStep;
28 28
 
29 29
 class RepairInvalidPaths implements IRepairStep {
30
-	/** @var IDBConnection */
31
-	private $connection;
32
-
33
-	public function __construct(IDBConnection $connection) {
34
-		$this->connection = $connection;
35
-	}
36
-
37
-
38
-	public function getName() {
39
-		return 'Repair invalid paths in file cache';
40
-	}
41
-
42
-	private function getInvalidEntries() {
43
-		$builder = $this->connection->getQueryBuilder();
44
-
45
-		$computedPath = $builder->func()->concat(
46
-			'p.path',
47
-			$builder->func()->concat($builder->createNamedParameter('/'), 'f.name')
48
-		);
49
-
50
-		//select f.path, f.parent,p.path from oc_filecache f inner join oc_filecache p on f.parent=p.fileid and p.path!='' where f.path != p.path || '/' || f.name;
51
-		$query = $builder->select('f.fileid', 'f.path', 'p.path AS parent_path', 'f.name', 'f.parent', 'f.storage')
52
-			->from('filecache', 'f')
53
-			->innerJoin('f', 'filecache', 'p', $builder->expr()->andX(
54
-				$builder->expr()->eq('f.parent', 'p.fileid'),
55
-				$builder->expr()->neq('p.name', $builder->createNamedParameter(''))
56
-			))
57
-			->where($builder->expr()->neq('f.path', $computedPath));
58
-
59
-		return $query->execute()->fetchAll();
60
-	}
61
-
62
-	private function getId($storage, $path) {
63
-		$builder = $this->connection->getQueryBuilder();
64
-
65
-		$query = $builder->select('fileid')
66
-			->from('filecache')
67
-			->where($builder->expr()->eq('storage', $builder->createNamedParameter($storage)))
68
-			->andWhere($builder->expr()->eq('path', $builder->createNamedParameter($path)));
69
-
70
-		return $query->execute()->fetchColumn();
71
-	}
72
-
73
-	private function update($fileid, $newPath) {
74
-		$builder = $this->connection->getQueryBuilder();
75
-
76
-		$query = $builder->update('filecache')
77
-			->set('path', $builder->createNamedParameter($newPath))
78
-			->set('path_hash', $builder->createNamedParameter(md5($newPath)))
79
-			->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileid)));
80
-
81
-		$query->execute();
82
-	}
83
-
84
-	private function reparent($from, $to) {
85
-		$builder = $this->connection->getQueryBuilder();
86
-
87
-		$query = $builder->update('filecache')
88
-			->set('parent', $builder->createNamedParameter($to))
89
-			->where($builder->expr()->eq('fileid', $builder->createNamedParameter($from)));
90
-		$query->execute();
91
-	}
92
-
93
-	private function delete($fileid) {
94
-		$builder = $this->connection->getQueryBuilder();
95
-
96
-		$query = $builder->delete('filecache')
97
-			->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileid)));
98
-		$query->execute();
99
-	}
100
-
101
-	private function repair() {
102
-		$entries = $this->getInvalidEntries();
103
-		foreach ($entries as $entry) {
104
-			$calculatedPath = $entry['parent_path'] . '/' . $entry['name'];
105
-			if ($newId = $this->getId($entry['storage'], $calculatedPath)) {
106
-				// a new entry with the correct path has already been created, reuse that one and delete the incorrect entry
107
-				$this->reparent($entry['fileid'], $newId);
108
-				$this->delete($entry['fileid']);
109
-			} else {
110
-				$this->update($entry['fileid'], $calculatedPath);
111
-			}
112
-		}
113
-		return count($entries);
114
-	}
115
-
116
-	public function run(IOutput $output) {
117
-		$count = $this->repair();
118
-
119
-		$output->info('Repaired ' . $count . ' paths');
120
-	}
30
+    /** @var IDBConnection */
31
+    private $connection;
32
+
33
+    public function __construct(IDBConnection $connection) {
34
+        $this->connection = $connection;
35
+    }
36
+
37
+
38
+    public function getName() {
39
+        return 'Repair invalid paths in file cache';
40
+    }
41
+
42
+    private function getInvalidEntries() {
43
+        $builder = $this->connection->getQueryBuilder();
44
+
45
+        $computedPath = $builder->func()->concat(
46
+            'p.path',
47
+            $builder->func()->concat($builder->createNamedParameter('/'), 'f.name')
48
+        );
49
+
50
+        //select f.path, f.parent,p.path from oc_filecache f inner join oc_filecache p on f.parent=p.fileid and p.path!='' where f.path != p.path || '/' || f.name;
51
+        $query = $builder->select('f.fileid', 'f.path', 'p.path AS parent_path', 'f.name', 'f.parent', 'f.storage')
52
+            ->from('filecache', 'f')
53
+            ->innerJoin('f', 'filecache', 'p', $builder->expr()->andX(
54
+                $builder->expr()->eq('f.parent', 'p.fileid'),
55
+                $builder->expr()->neq('p.name', $builder->createNamedParameter(''))
56
+            ))
57
+            ->where($builder->expr()->neq('f.path', $computedPath));
58
+
59
+        return $query->execute()->fetchAll();
60
+    }
61
+
62
+    private function getId($storage, $path) {
63
+        $builder = $this->connection->getQueryBuilder();
64
+
65
+        $query = $builder->select('fileid')
66
+            ->from('filecache')
67
+            ->where($builder->expr()->eq('storage', $builder->createNamedParameter($storage)))
68
+            ->andWhere($builder->expr()->eq('path', $builder->createNamedParameter($path)));
69
+
70
+        return $query->execute()->fetchColumn();
71
+    }
72
+
73
+    private function update($fileid, $newPath) {
74
+        $builder = $this->connection->getQueryBuilder();
75
+
76
+        $query = $builder->update('filecache')
77
+            ->set('path', $builder->createNamedParameter($newPath))
78
+            ->set('path_hash', $builder->createNamedParameter(md5($newPath)))
79
+            ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileid)));
80
+
81
+        $query->execute();
82
+    }
83
+
84
+    private function reparent($from, $to) {
85
+        $builder = $this->connection->getQueryBuilder();
86
+
87
+        $query = $builder->update('filecache')
88
+            ->set('parent', $builder->createNamedParameter($to))
89
+            ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($from)));
90
+        $query->execute();
91
+    }
92
+
93
+    private function delete($fileid) {
94
+        $builder = $this->connection->getQueryBuilder();
95
+
96
+        $query = $builder->delete('filecache')
97
+            ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileid)));
98
+        $query->execute();
99
+    }
100
+
101
+    private function repair() {
102
+        $entries = $this->getInvalidEntries();
103
+        foreach ($entries as $entry) {
104
+            $calculatedPath = $entry['parent_path'] . '/' . $entry['name'];
105
+            if ($newId = $this->getId($entry['storage'], $calculatedPath)) {
106
+                // a new entry with the correct path has already been created, reuse that one and delete the incorrect entry
107
+                $this->reparent($entry['fileid'], $newId);
108
+                $this->delete($entry['fileid']);
109
+            } else {
110
+                $this->update($entry['fileid'], $calculatedPath);
111
+            }
112
+        }
113
+        return count($entries);
114
+    }
115
+
116
+    public function run(IOutput $output) {
117
+        $count = $this->repair();
118
+
119
+        $output->info('Repaired ' . $count . ' paths');
120
+    }
121 121
 }
Please login to merge, or discard this patch.
lib/private/Repair.php 1 patch
Indentation   +175 added lines, -175 removed lines patch added patch discarded remove patch
@@ -53,179 +53,179 @@
 block discarded – undo
53 53
 use Symfony\Component\EventDispatcher\GenericEvent;
54 54
 
55 55
 class Repair implements IOutput{
56
-	/* @var IRepairStep[] */
57
-	private $repairSteps;
58
-	/** @var EventDispatcher */
59
-	private $dispatcher;
60
-	/** @var string */
61
-	private $currentStep;
62
-
63
-	/**
64
-	 * Creates a new repair step runner
65
-	 *
66
-	 * @param IRepairStep[] $repairSteps array of RepairStep instances
67
-	 * @param EventDispatcher $dispatcher
68
-	 */
69
-	public function __construct($repairSteps = [], EventDispatcher $dispatcher = null) {
70
-		$this->repairSteps = $repairSteps;
71
-		$this->dispatcher = $dispatcher;
72
-	}
73
-
74
-	/**
75
-	 * Run a series of repair steps for common problems
76
-	 */
77
-	public function run() {
78
-		if (count($this->repairSteps) === 0) {
79
-			$this->emit('\OC\Repair', 'info', array('No repair steps available'));
80
-			return;
81
-		}
82
-		// run each repair step
83
-		foreach ($this->repairSteps as $step) {
84
-			$this->currentStep = $step->getName();
85
-			$this->emit('\OC\Repair', 'step', [$this->currentStep]);
86
-			$step->run($this);
87
-		}
88
-	}
89
-
90
-	/**
91
-	 * Add repair step
92
-	 *
93
-	 * @param IRepairStep|string $repairStep repair step
94
-	 * @throws \Exception
95
-	 */
96
-	public function addStep($repairStep) {
97
-		if (is_string($repairStep)) {
98
-			try {
99
-				$s = \OC::$server->query($repairStep);
100
-			} catch (QueryException $e) {
101
-				if (class_exists($repairStep)) {
102
-					$s = new $repairStep();
103
-				} else {
104
-					throw new \Exception("Repair step '$repairStep' is unknown");
105
-				}
106
-			}
107
-
108
-			if ($s instanceof IRepairStep) {
109
-				$this->repairSteps[] = $s;
110
-			} else {
111
-				throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
112
-			}
113
-		} else {
114
-			$this->repairSteps[] = $repairStep;
115
-		}
116
-	}
117
-
118
-	/**
119
-	 * Returns the default repair steps to be run on the
120
-	 * command line or after an upgrade.
121
-	 *
122
-	 * @return IRepairStep[]
123
-	 */
124
-	public static function getRepairSteps() {
125
-		return [
126
-			new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), \OC::$server->getDatabaseConnection(), false),
127
-			new RepairMimeTypes(\OC::$server->getConfig()),
128
-			new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
129
-			new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
130
-			new RemoveRootShares(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager(), \OC::$server->getLazyRootFolder()),
131
-			new MoveUpdaterStepFile(\OC::$server->getConfig()),
132
-			new MoveAvatars(
133
-				\OC::$server->getJobList(),
134
-				\OC::$server->getConfig()
135
-			),
136
-			new CleanPreviews(
137
-				\OC::$server->getJobList(),
138
-				\OC::$server->getUserManager(),
139
-				\OC::$server->getConfig()
140
-			),
141
-			new FixMountStorages(\OC::$server->getDatabaseConnection()),
142
-			new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
143
-			new InstallCoreBundle(
144
-				\OC::$server->query(BundleFetcher::class),
145
-				\OC::$server->getConfig(),
146
-				\OC::$server->query(Installer::class)
147
-			),
148
-			new RepairInvalidPaths(\OC::$server->getDatabaseConnection())
149
-		];
150
-	}
151
-
152
-	/**
153
-	 * Returns expensive repair steps to be run on the
154
-	 * command line with a special option.
155
-	 *
156
-	 * @return IRepairStep[]
157
-	 */
158
-	public static function getExpensiveRepairSteps() {
159
-		return [
160
-			new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager())
161
-		];
162
-	}
163
-
164
-	/**
165
-	 * Returns the repair steps to be run before an
166
-	 * upgrade.
167
-	 *
168
-	 * @return IRepairStep[]
169
-	 */
170
-	public static function getBeforeUpgradeRepairSteps() {
171
-		$connection = \OC::$server->getDatabaseConnection();
172
-		$config = \OC::$server->getConfig();
173
-		$steps = [
174
-			new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connection, true),
175
-			new SqliteAutoincrement($connection),
176
-			new SaveAccountsTableData($connection, $config),
177
-		];
178
-
179
-		return $steps;
180
-	}
181
-
182
-	/**
183
-	 * @param string $scope
184
-	 * @param string $method
185
-	 * @param array $arguments
186
-	 */
187
-	public function emit($scope, $method, array $arguments = []) {
188
-		if (!is_null($this->dispatcher)) {
189
-			$this->dispatcher->dispatch("$scope::$method",
190
-				new GenericEvent("$scope::$method", $arguments));
191
-		}
192
-	}
193
-
194
-	public function info($string) {
195
-		// for now just emit as we did in the past
196
-		$this->emit('\OC\Repair', 'info', array($string));
197
-	}
198
-
199
-	/**
200
-	 * @param string $message
201
-	 */
202
-	public function warning($message) {
203
-		// for now just emit as we did in the past
204
-		$this->emit('\OC\Repair', 'warning', [$message]);
205
-	}
206
-
207
-	/**
208
-	 * @param int $max
209
-	 */
210
-	public function startProgress($max = 0) {
211
-		// for now just emit as we did in the past
212
-		$this->emit('\OC\Repair', 'startProgress', [$max, $this->currentStep]);
213
-	}
214
-
215
-	/**
216
-	 * @param int $step
217
-	 * @param string $description
218
-	 */
219
-	public function advance($step = 1, $description = '') {
220
-		// for now just emit as we did in the past
221
-		$this->emit('\OC\Repair', 'advance', [$step, $description]);
222
-	}
223
-
224
-	/**
225
-	 * @param int $max
226
-	 */
227
-	public function finishProgress() {
228
-		// for now just emit as we did in the past
229
-		$this->emit('\OC\Repair', 'finishProgress', []);
230
-	}
56
+    /* @var IRepairStep[] */
57
+    private $repairSteps;
58
+    /** @var EventDispatcher */
59
+    private $dispatcher;
60
+    /** @var string */
61
+    private $currentStep;
62
+
63
+    /**
64
+     * Creates a new repair step runner
65
+     *
66
+     * @param IRepairStep[] $repairSteps array of RepairStep instances
67
+     * @param EventDispatcher $dispatcher
68
+     */
69
+    public function __construct($repairSteps = [], EventDispatcher $dispatcher = null) {
70
+        $this->repairSteps = $repairSteps;
71
+        $this->dispatcher = $dispatcher;
72
+    }
73
+
74
+    /**
75
+     * Run a series of repair steps for common problems
76
+     */
77
+    public function run() {
78
+        if (count($this->repairSteps) === 0) {
79
+            $this->emit('\OC\Repair', 'info', array('No repair steps available'));
80
+            return;
81
+        }
82
+        // run each repair step
83
+        foreach ($this->repairSteps as $step) {
84
+            $this->currentStep = $step->getName();
85
+            $this->emit('\OC\Repair', 'step', [$this->currentStep]);
86
+            $step->run($this);
87
+        }
88
+    }
89
+
90
+    /**
91
+     * Add repair step
92
+     *
93
+     * @param IRepairStep|string $repairStep repair step
94
+     * @throws \Exception
95
+     */
96
+    public function addStep($repairStep) {
97
+        if (is_string($repairStep)) {
98
+            try {
99
+                $s = \OC::$server->query($repairStep);
100
+            } catch (QueryException $e) {
101
+                if (class_exists($repairStep)) {
102
+                    $s = new $repairStep();
103
+                } else {
104
+                    throw new \Exception("Repair step '$repairStep' is unknown");
105
+                }
106
+            }
107
+
108
+            if ($s instanceof IRepairStep) {
109
+                $this->repairSteps[] = $s;
110
+            } else {
111
+                throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
112
+            }
113
+        } else {
114
+            $this->repairSteps[] = $repairStep;
115
+        }
116
+    }
117
+
118
+    /**
119
+     * Returns the default repair steps to be run on the
120
+     * command line or after an upgrade.
121
+     *
122
+     * @return IRepairStep[]
123
+     */
124
+    public static function getRepairSteps() {
125
+        return [
126
+            new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), \OC::$server->getDatabaseConnection(), false),
127
+            new RepairMimeTypes(\OC::$server->getConfig()),
128
+            new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
129
+            new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
130
+            new RemoveRootShares(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager(), \OC::$server->getLazyRootFolder()),
131
+            new MoveUpdaterStepFile(\OC::$server->getConfig()),
132
+            new MoveAvatars(
133
+                \OC::$server->getJobList(),
134
+                \OC::$server->getConfig()
135
+            ),
136
+            new CleanPreviews(
137
+                \OC::$server->getJobList(),
138
+                \OC::$server->getUserManager(),
139
+                \OC::$server->getConfig()
140
+            ),
141
+            new FixMountStorages(\OC::$server->getDatabaseConnection()),
142
+            new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
143
+            new InstallCoreBundle(
144
+                \OC::$server->query(BundleFetcher::class),
145
+                \OC::$server->getConfig(),
146
+                \OC::$server->query(Installer::class)
147
+            ),
148
+            new RepairInvalidPaths(\OC::$server->getDatabaseConnection())
149
+        ];
150
+    }
151
+
152
+    /**
153
+     * Returns expensive repair steps to be run on the
154
+     * command line with a special option.
155
+     *
156
+     * @return IRepairStep[]
157
+     */
158
+    public static function getExpensiveRepairSteps() {
159
+        return [
160
+            new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager())
161
+        ];
162
+    }
163
+
164
+    /**
165
+     * Returns the repair steps to be run before an
166
+     * upgrade.
167
+     *
168
+     * @return IRepairStep[]
169
+     */
170
+    public static function getBeforeUpgradeRepairSteps() {
171
+        $connection = \OC::$server->getDatabaseConnection();
172
+        $config = \OC::$server->getConfig();
173
+        $steps = [
174
+            new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connection, true),
175
+            new SqliteAutoincrement($connection),
176
+            new SaveAccountsTableData($connection, $config),
177
+        ];
178
+
179
+        return $steps;
180
+    }
181
+
182
+    /**
183
+     * @param string $scope
184
+     * @param string $method
185
+     * @param array $arguments
186
+     */
187
+    public function emit($scope, $method, array $arguments = []) {
188
+        if (!is_null($this->dispatcher)) {
189
+            $this->dispatcher->dispatch("$scope::$method",
190
+                new GenericEvent("$scope::$method", $arguments));
191
+        }
192
+    }
193
+
194
+    public function info($string) {
195
+        // for now just emit as we did in the past
196
+        $this->emit('\OC\Repair', 'info', array($string));
197
+    }
198
+
199
+    /**
200
+     * @param string $message
201
+     */
202
+    public function warning($message) {
203
+        // for now just emit as we did in the past
204
+        $this->emit('\OC\Repair', 'warning', [$message]);
205
+    }
206
+
207
+    /**
208
+     * @param int $max
209
+     */
210
+    public function startProgress($max = 0) {
211
+        // for now just emit as we did in the past
212
+        $this->emit('\OC\Repair', 'startProgress', [$max, $this->currentStep]);
213
+    }
214
+
215
+    /**
216
+     * @param int $step
217
+     * @param string $description
218
+     */
219
+    public function advance($step = 1, $description = '') {
220
+        // for now just emit as we did in the past
221
+        $this->emit('\OC\Repair', 'advance', [$step, $description]);
222
+    }
223
+
224
+    /**
225
+     * @param int $max
226
+     */
227
+    public function finishProgress() {
228
+        // for now just emit as we did in the past
229
+        $this->emit('\OC\Repair', 'finishProgress', []);
230
+    }
231 231
 }
Please login to merge, or discard this patch.