Completed
Pull Request — master (#4004)
by Morris
26:20 queued 15:00
created
lib/private/Files/Cache/Cache.php 2 patches
Indentation   +818 added lines, -818 removed lines patch added patch discarded remove patch
@@ -55,832 +55,832 @@
 block discarded – undo
55 55
  * - ChangePropagator: updates the mtime and etags of parent folders whenever a change to the cache is made to the cache by the updater
56 56
  */
57 57
 class Cache implements ICache {
58
-	use MoveFromCacheTrait {
59
-		MoveFromCacheTrait::moveFromCache as moveFromCacheFallback;
60
-	}
61
-
62
-	/**
63
-	 * @var array partial data for the cache
64
-	 */
65
-	protected $partial = array();
66
-
67
-	/**
68
-	 * @var string
69
-	 */
70
-	protected $storageId;
71
-
72
-	/**
73
-	 * @var Storage $storageCache
74
-	 */
75
-	protected $storageCache;
76
-
77
-	/** @var IMimeTypeLoader */
78
-	protected $mimetypeLoader;
79
-
80
-	/**
81
-	 * @var IDBConnection
82
-	 */
83
-	protected $connection;
84
-
85
-	/** @var QuerySearchHelper */
86
-	protected $querySearchHelper;
87
-
88
-	/**
89
-	 * @param \OC\Files\Storage\Storage|string $storage
90
-	 */
91
-	public function __construct($storage) {
92
-		if ($storage instanceof \OC\Files\Storage\Storage) {
93
-			$this->storageId = $storage->getId();
94
-		} else {
95
-			$this->storageId = $storage;
96
-		}
97
-		if (strlen($this->storageId) > 64) {
98
-			$this->storageId = md5($this->storageId);
99
-		}
100
-
101
-		$this->storageCache = new Storage($storage);
102
-		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
103
-		$this->connection = \OC::$server->getDatabaseConnection();
104
-		$this->querySearchHelper = new QuerySearchHelper($this->mimetypeLoader);
105
-	}
106
-
107
-	/**
108
-	 * Get the numeric storage id for this cache's storage
109
-	 *
110
-	 * @return int
111
-	 */
112
-	public function getNumericStorageId() {
113
-		return $this->storageCache->getNumericId();
114
-	}
115
-
116
-	/**
117
-	 * get the stored metadata of a file or folder
118
-	 *
119
-	 * @param string | int $file either the path of a file or folder or the file id for a file or folder
120
-	 * @return ICacheEntry|false the cache entry as array of false if the file is not found in the cache
121
-	 */
122
-	public function get($file) {
123
-		if (is_string($file) or $file == '') {
124
-			// normalize file
125
-			$file = $this->normalize($file);
126
-
127
-			$where = 'WHERE `storage` = ? AND `path_hash` = ?';
128
-			$params = array($this->getNumericStorageId(), md5($file));
129
-		} else { //file id
130
-			$where = 'WHERE `fileid` = ?';
131
-			$params = array($file);
132
-		}
133
-		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
58
+    use MoveFromCacheTrait {
59
+        MoveFromCacheTrait::moveFromCache as moveFromCacheFallback;
60
+    }
61
+
62
+    /**
63
+     * @var array partial data for the cache
64
+     */
65
+    protected $partial = array();
66
+
67
+    /**
68
+     * @var string
69
+     */
70
+    protected $storageId;
71
+
72
+    /**
73
+     * @var Storage $storageCache
74
+     */
75
+    protected $storageCache;
76
+
77
+    /** @var IMimeTypeLoader */
78
+    protected $mimetypeLoader;
79
+
80
+    /**
81
+     * @var IDBConnection
82
+     */
83
+    protected $connection;
84
+
85
+    /** @var QuerySearchHelper */
86
+    protected $querySearchHelper;
87
+
88
+    /**
89
+     * @param \OC\Files\Storage\Storage|string $storage
90
+     */
91
+    public function __construct($storage) {
92
+        if ($storage instanceof \OC\Files\Storage\Storage) {
93
+            $this->storageId = $storage->getId();
94
+        } else {
95
+            $this->storageId = $storage;
96
+        }
97
+        if (strlen($this->storageId) > 64) {
98
+            $this->storageId = md5($this->storageId);
99
+        }
100
+
101
+        $this->storageCache = new Storage($storage);
102
+        $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
103
+        $this->connection = \OC::$server->getDatabaseConnection();
104
+        $this->querySearchHelper = new QuerySearchHelper($this->mimetypeLoader);
105
+    }
106
+
107
+    /**
108
+     * Get the numeric storage id for this cache's storage
109
+     *
110
+     * @return int
111
+     */
112
+    public function getNumericStorageId() {
113
+        return $this->storageCache->getNumericId();
114
+    }
115
+
116
+    /**
117
+     * get the stored metadata of a file or folder
118
+     *
119
+     * @param string | int $file either the path of a file or folder or the file id for a file or folder
120
+     * @return ICacheEntry|false the cache entry as array of false if the file is not found in the cache
121
+     */
122
+    public function get($file) {
123
+        if (is_string($file) or $file == '') {
124
+            // normalize file
125
+            $file = $this->normalize($file);
126
+
127
+            $where = 'WHERE `storage` = ? AND `path_hash` = ?';
128
+            $params = array($this->getNumericStorageId(), md5($file));
129
+        } else { //file id
130
+            $where = 'WHERE `fileid` = ?';
131
+            $params = array($file);
132
+        }
133
+        $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
134 134
 					   `storage_mtime`, `encrypted`, `etag`, `permissions`, `checksum`
135 135
 				FROM `*PREFIX*filecache` ' . $where;
136
-		$result = $this->connection->executeQuery($sql, $params);
137
-		$data = $result->fetch();
138
-
139
-		//FIXME hide this HACK in the next database layer, or just use doctrine and get rid of MDB2 and PDO
140
-		//PDO returns false, MDB2 returns null, oracle always uses MDB2, so convert null to false
141
-		if ($data === null) {
142
-			$data = false;
143
-		}
144
-
145
-		//merge partial data
146
-		if (!$data and is_string($file)) {
147
-			if (isset($this->partial[$file])) {
148
-				$data = $this->partial[$file];
149
-			}
150
-			return $data;
151
-		} else {
152
-			return self::cacheEntryFromData($data, $this->mimetypeLoader);
153
-		}
154
-	}
155
-
156
-	/**
157
-	 * Create a CacheEntry from database row
158
-	 *
159
-	 * @param array $data
160
-	 * @param IMimeTypeLoader $mimetypeLoader
161
-	 * @return CacheEntry
162
-	 */
163
-	public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) {
164
-		//fix types
165
-		$data['fileid'] = (int)$data['fileid'];
166
-		$data['parent'] = (int)$data['parent'];
167
-		$data['size'] = 0 + $data['size'];
168
-		$data['mtime'] = (int)$data['mtime'];
169
-		$data['storage_mtime'] = (int)$data['storage_mtime'];
170
-		$data['encryptedVersion'] = (int)$data['encrypted'];
171
-		$data['encrypted'] = (bool)$data['encrypted'];
172
-		$data['storage_id'] = $data['storage'];
173
-		$data['storage'] = (int)$data['storage'];
174
-		$data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
175
-		$data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
176
-		if ($data['storage_mtime'] == 0) {
177
-			$data['storage_mtime'] = $data['mtime'];
178
-		}
179
-		$data['permissions'] = (int)$data['permissions'];
180
-		return new CacheEntry($data);
181
-	}
182
-
183
-	/**
184
-	 * get the metadata of all files stored in $folder
185
-	 *
186
-	 * @param string $folder
187
-	 * @return ICacheEntry[]
188
-	 */
189
-	public function getFolderContents($folder) {
190
-		$fileId = $this->getId($folder);
191
-		return $this->getFolderContentsById($fileId);
192
-	}
193
-
194
-	/**
195
-	 * get the metadata of all files stored in $folder
196
-	 *
197
-	 * @param int $fileId the file id of the folder
198
-	 * @return ICacheEntry[]
199
-	 */
200
-	public function getFolderContentsById($fileId) {
201
-		if ($fileId > -1) {
202
-			$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
136
+        $result = $this->connection->executeQuery($sql, $params);
137
+        $data = $result->fetch();
138
+
139
+        //FIXME hide this HACK in the next database layer, or just use doctrine and get rid of MDB2 and PDO
140
+        //PDO returns false, MDB2 returns null, oracle always uses MDB2, so convert null to false
141
+        if ($data === null) {
142
+            $data = false;
143
+        }
144
+
145
+        //merge partial data
146
+        if (!$data and is_string($file)) {
147
+            if (isset($this->partial[$file])) {
148
+                $data = $this->partial[$file];
149
+            }
150
+            return $data;
151
+        } else {
152
+            return self::cacheEntryFromData($data, $this->mimetypeLoader);
153
+        }
154
+    }
155
+
156
+    /**
157
+     * Create a CacheEntry from database row
158
+     *
159
+     * @param array $data
160
+     * @param IMimeTypeLoader $mimetypeLoader
161
+     * @return CacheEntry
162
+     */
163
+    public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) {
164
+        //fix types
165
+        $data['fileid'] = (int)$data['fileid'];
166
+        $data['parent'] = (int)$data['parent'];
167
+        $data['size'] = 0 + $data['size'];
168
+        $data['mtime'] = (int)$data['mtime'];
169
+        $data['storage_mtime'] = (int)$data['storage_mtime'];
170
+        $data['encryptedVersion'] = (int)$data['encrypted'];
171
+        $data['encrypted'] = (bool)$data['encrypted'];
172
+        $data['storage_id'] = $data['storage'];
173
+        $data['storage'] = (int)$data['storage'];
174
+        $data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
175
+        $data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
176
+        if ($data['storage_mtime'] == 0) {
177
+            $data['storage_mtime'] = $data['mtime'];
178
+        }
179
+        $data['permissions'] = (int)$data['permissions'];
180
+        return new CacheEntry($data);
181
+    }
182
+
183
+    /**
184
+     * get the metadata of all files stored in $folder
185
+     *
186
+     * @param string $folder
187
+     * @return ICacheEntry[]
188
+     */
189
+    public function getFolderContents($folder) {
190
+        $fileId = $this->getId($folder);
191
+        return $this->getFolderContentsById($fileId);
192
+    }
193
+
194
+    /**
195
+     * get the metadata of all files stored in $folder
196
+     *
197
+     * @param int $fileId the file id of the folder
198
+     * @return ICacheEntry[]
199
+     */
200
+    public function getFolderContentsById($fileId) {
201
+        if ($fileId > -1) {
202
+            $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
203 203
 						   `storage_mtime`, `encrypted`, `etag`, `permissions`, `checksum`
204 204
 					FROM `*PREFIX*filecache` WHERE `parent` = ? ORDER BY `name` ASC';
205
-			$result = $this->connection->executeQuery($sql, [$fileId]);
206
-			$files = $result->fetchAll();
207
-			return array_map(function (array $data) {
208
-				return self::cacheEntryFromData($data, $this->mimetypeLoader);;
209
-			}, $files);
210
-		} else {
211
-			return array();
212
-		}
213
-	}
214
-
215
-	/**
216
-	 * insert or update meta data for a file or folder
217
-	 *
218
-	 * @param string $file
219
-	 * @param array $data
220
-	 *
221
-	 * @return int file id
222
-	 * @throws \RuntimeException
223
-	 */
224
-	public function put($file, array $data) {
225
-		if (($id = $this->getId($file)) > -1) {
226
-			$this->update($id, $data);
227
-			return $id;
228
-		} else {
229
-			return $this->insert($file, $data);
230
-		}
231
-	}
232
-
233
-	/**
234
-	 * insert meta data for a new file or folder
235
-	 *
236
-	 * @param string $file
237
-	 * @param array $data
238
-	 *
239
-	 * @return int file id
240
-	 * @throws \RuntimeException
241
-	 */
242
-	public function insert($file, array $data) {
243
-		// normalize file
244
-		$file = $this->normalize($file);
245
-
246
-		if (isset($this->partial[$file])) { //add any saved partial data
247
-			$data = array_merge($this->partial[$file], $data);
248
-			unset($this->partial[$file]);
249
-		}
250
-
251
-		$requiredFields = array('size', 'mtime', 'mimetype');
252
-		foreach ($requiredFields as $field) {
253
-			if (!isset($data[$field])) { //data not complete save as partial and return
254
-				$this->partial[$file] = $data;
255
-				return -1;
256
-			}
257
-		}
258
-
259
-		$data['path'] = $file;
260
-		$data['parent'] = $this->getParentId($file);
261
-		$data['name'] = \OC_Util::basename($file);
262
-
263
-		list($queryParts, $params) = $this->buildParts($data);
264
-		$queryParts[] = '`storage`';
265
-		$params[] = $this->getNumericStorageId();
266
-
267
-		$queryParts = array_map(function ($item) {
268
-			return trim($item, "`");
269
-		}, $queryParts);
270
-		$values = array_combine($queryParts, $params);
271
-		if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [
272
-			'storage',
273
-			'path_hash',
274
-		])
275
-		) {
276
-			return (int)$this->connection->lastInsertId('*PREFIX*filecache');
277
-		}
278
-
279
-		// The file was created in the mean time
280
-		if (($id = $this->getId($file)) > -1) {
281
-			$this->update($id, $data);
282
-			return $id;
283
-		} else {
284
-			throw new \RuntimeException('File entry could not be inserted with insertIfNotExist() but could also not be selected with getId() in order to perform an update. Please try again.');
285
-		}
286
-	}
287
-
288
-	/**
289
-	 * update the metadata of an existing file or folder in the cache
290
-	 *
291
-	 * @param int $id the fileid of the existing file or folder
292
-	 * @param array $data [$key => $value] the metadata to update, only the fields provided in the array will be updated, non-provided values will remain unchanged
293
-	 */
294
-	public function update($id, array $data) {
295
-
296
-		if (isset($data['path'])) {
297
-			// normalize path
298
-			$data['path'] = $this->normalize($data['path']);
299
-		}
300
-
301
-		if (isset($data['name'])) {
302
-			// normalize path
303
-			$data['name'] = $this->normalize($data['name']);
304
-		}
305
-
306
-		list($queryParts, $params) = $this->buildParts($data);
307
-		// duplicate $params because we need the parts twice in the SQL statement
308
-		// once for the SET part, once in the WHERE clause
309
-		$params = array_merge($params, $params);
310
-		$params[] = $id;
311
-
312
-		// don't update if the data we try to set is the same as the one in the record
313
-		// some databases (Postgres) don't like superfluous updates
314
-		$sql = 'UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? ' .
315
-			'WHERE (' .
316
-			implode(' <> ? OR ', $queryParts) . ' <> ? OR ' .
317
-			implode(' IS NULL OR ', $queryParts) . ' IS NULL' .
318
-			') AND `fileid` = ? ';
319
-		$this->connection->executeQuery($sql, $params);
320
-
321
-	}
322
-
323
-	/**
324
-	 * extract query parts and params array from data array
325
-	 *
326
-	 * @param array $data
327
-	 * @return array [$queryParts, $params]
328
-	 *        $queryParts: string[], the (escaped) column names to be set in the query
329
-	 *        $params: mixed[], the new values for the columns, to be passed as params to the query
330
-	 */
331
-	protected function buildParts(array $data) {
332
-		$fields = array(
333
-			'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted',
334
-			'etag', 'permissions', 'checksum');
335
-
336
-		$doNotCopyStorageMTime = false;
337
-		if (array_key_exists('mtime', $data) && $data['mtime'] === null) {
338
-			// this horrific magic tells it to not copy storage_mtime to mtime
339
-			unset($data['mtime']);
340
-			$doNotCopyStorageMTime = true;
341
-		}
342
-
343
-		$params = array();
344
-		$queryParts = array();
345
-		foreach ($data as $name => $value) {
346
-			if (array_search($name, $fields) !== false) {
347
-				if ($name === 'path') {
348
-					$params[] = md5($value);
349
-					$queryParts[] = '`path_hash`';
350
-				} elseif ($name === 'mimetype') {
351
-					$params[] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
352
-					$queryParts[] = '`mimepart`';
353
-					$value = $this->mimetypeLoader->getId($value);
354
-				} elseif ($name === 'storage_mtime') {
355
-					if (!$doNotCopyStorageMTime && !isset($data['mtime'])) {
356
-						$params[] = $value;
357
-						$queryParts[] = '`mtime`';
358
-					}
359
-				} elseif ($name === 'encrypted') {
360
-					if (isset($data['encryptedVersion'])) {
361
-						$value = $data['encryptedVersion'];
362
-					} else {
363
-						// Boolean to integer conversion
364
-						$value = $value ? 1 : 0;
365
-					}
366
-				}
367
-				$params[] = $value;
368
-				$queryParts[] = '`' . $name . '`';
369
-			}
370
-		}
371
-		return array($queryParts, $params);
372
-	}
373
-
374
-	/**
375
-	 * get the file id for a file
376
-	 *
377
-	 * A file id is a numeric id for a file or folder that's unique within an owncloud instance which stays the same for the lifetime of a file
378
-	 *
379
-	 * File ids are easiest way for apps to store references to a file since unlike paths they are not affected by renames or sharing
380
-	 *
381
-	 * @param string $file
382
-	 * @return int
383
-	 */
384
-	public function getId($file) {
385
-		// normalize file
386
-		$file = $this->normalize($file);
387
-
388
-		$pathHash = md5($file);
389
-
390
-		$sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
391
-		$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
392
-		if ($row = $result->fetch()) {
393
-			return $row['fileid'];
394
-		} else {
395
-			return -1;
396
-		}
397
-	}
398
-
399
-	/**
400
-	 * get the id of the parent folder of a file
401
-	 *
402
-	 * @param string $file
403
-	 * @return int
404
-	 */
405
-	public function getParentId($file) {
406
-		if ($file === '') {
407
-			return -1;
408
-		} else {
409
-			$parent = $this->getParentPath($file);
410
-			return (int)$this->getId($parent);
411
-		}
412
-	}
413
-
414
-	private function getParentPath($path) {
415
-		$parent = dirname($path);
416
-		if ($parent === '.') {
417
-			$parent = '';
418
-		}
419
-		return $parent;
420
-	}
421
-
422
-	/**
423
-	 * check if a file is available in the cache
424
-	 *
425
-	 * @param string $file
426
-	 * @return bool
427
-	 */
428
-	public function inCache($file) {
429
-		return $this->getId($file) != -1;
430
-	}
431
-
432
-	/**
433
-	 * remove a file or folder from the cache
434
-	 *
435
-	 * when removing a folder from the cache all files and folders inside the folder will be removed as well
436
-	 *
437
-	 * @param string $file
438
-	 */
439
-	public function remove($file) {
440
-		$entry = $this->get($file);
441
-		$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
442
-		$this->connection->executeQuery($sql, array($entry['fileid']));
443
-		if ($entry['mimetype'] === 'httpd/unix-directory') {
444
-			$this->removeChildren($entry);
445
-		}
446
-	}
447
-
448
-	/**
449
-	 * Get all sub folders of a folder
450
-	 *
451
-	 * @param array $entry the cache entry of the folder to get the subfolders for
452
-	 * @return array[] the cache entries for the subfolders
453
-	 */
454
-	private function getSubFolders($entry) {
455
-		$children = $this->getFolderContentsById($entry['fileid']);
456
-		return array_filter($children, function ($child) {
457
-			return $child['mimetype'] === 'httpd/unix-directory';
458
-		});
459
-	}
460
-
461
-	/**
462
-	 * Recursively remove all children of a folder
463
-	 *
464
-	 * @param array $entry the cache entry of the folder to remove the children of
465
-	 * @throws \OC\DatabaseException
466
-	 */
467
-	private function removeChildren($entry) {
468
-		$subFolders = $this->getSubFolders($entry);
469
-		foreach ($subFolders as $folder) {
470
-			$this->removeChildren($folder);
471
-		}
472
-		$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `parent` = ?';
473
-		$this->connection->executeQuery($sql, array($entry['fileid']));
474
-	}
475
-
476
-	/**
477
-	 * Move a file or folder in the cache
478
-	 *
479
-	 * @param string $source
480
-	 * @param string $target
481
-	 */
482
-	public function move($source, $target) {
483
-		$this->moveFromCache($this, $source, $target);
484
-	}
485
-
486
-	/**
487
-	 * Get the storage id and path needed for a move
488
-	 *
489
-	 * @param string $path
490
-	 * @return array [$storageId, $internalPath]
491
-	 */
492
-	protected function getMoveInfo($path) {
493
-		return [$this->getNumericStorageId(), $path];
494
-	}
495
-
496
-	/**
497
-	 * Move a file or folder in the cache
498
-	 *
499
-	 * @param \OCP\Files\Cache\ICache $sourceCache
500
-	 * @param string $sourcePath
501
-	 * @param string $targetPath
502
-	 * @throws \OC\DatabaseException
503
-	 * @throws \Exception if the given storages have an invalid id
504
-	 */
505
-	public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
506
-		if ($sourceCache instanceof Cache) {
507
-			// normalize source and target
508
-			$sourcePath = $this->normalize($sourcePath);
509
-			$targetPath = $this->normalize($targetPath);
510
-
511
-			$sourceData = $sourceCache->get($sourcePath);
512
-			$sourceId = $sourceData['fileid'];
513
-			$newParentId = $this->getParentId($targetPath);
514
-
515
-			list($sourceStorageId, $sourcePath) = $sourceCache->getMoveInfo($sourcePath);
516
-			list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath);
517
-
518
-			if (is_null($sourceStorageId) || $sourceStorageId === false) {
519
-				throw new \Exception('Invalid source storage id: ' . $sourceStorageId);
520
-			}
521
-			if (is_null($targetStorageId) || $targetStorageId === false) {
522
-				throw new \Exception('Invalid target storage id: ' . $targetStorageId);
523
-			}
524
-
525
-			// sql for final update
526
-			$moveSql = 'UPDATE `*PREFIX*filecache` SET `storage` =  ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` =? WHERE `fileid` = ?';
527
-
528
-			if ($sourceData['mimetype'] === 'httpd/unix-directory') {
529
-				//find all child entries
530
-				$sql = 'SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?';
531
-				$result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']);
532
-				$childEntries = $result->fetchAll();
533
-				$sourceLength = strlen($sourcePath);
534
-				$this->connection->beginTransaction();
535
-				$query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
536
-
537
-				foreach ($childEntries as $child) {
538
-					$newTargetPath = $targetPath . substr($child['path'], $sourceLength);
539
-					$query->execute([$targetStorageId, $newTargetPath, md5($newTargetPath), $child['fileid']]);
540
-				}
541
-				$this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
542
-				$this->connection->commit();
543
-			} else {
544
-				$this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), \OC_Util::basename($targetPath), $newParentId, $sourceId]);
545
-			}
546
-		} else {
547
-			$this->moveFromCacheFallback($sourceCache, $sourcePath, $targetPath);
548
-		}
549
-	}
550
-
551
-	/**
552
-	 * remove all entries for files that are stored on the storage from the cache
553
-	 */
554
-	public function clear() {
555
-		$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `storage` = ?';
556
-		$this->connection->executeQuery($sql, array($this->getNumericStorageId()));
557
-
558
-		$sql = 'DELETE FROM `*PREFIX*storages` WHERE `id` = ?';
559
-		$this->connection->executeQuery($sql, array($this->storageId));
560
-	}
561
-
562
-	/**
563
-	 * Get the scan status of a file
564
-	 *
565
-	 * - Cache::NOT_FOUND: File is not in the cache
566
-	 * - Cache::PARTIAL: File is not stored in the cache but some incomplete data is known
567
-	 * - Cache::SHALLOW: The folder and it's direct children are in the cache but not all sub folders are fully scanned
568
-	 * - Cache::COMPLETE: The file or folder, with all it's children) are fully scanned
569
-	 *
570
-	 * @param string $file
571
-	 *
572
-	 * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
573
-	 */
574
-	public function getStatus($file) {
575
-		// normalize file
576
-		$file = $this->normalize($file);
577
-
578
-		$pathHash = md5($file);
579
-		$sql = 'SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
580
-		$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
581
-		if ($row = $result->fetch()) {
582
-			if ((int)$row['size'] === -1) {
583
-				return self::SHALLOW;
584
-			} else {
585
-				return self::COMPLETE;
586
-			}
587
-		} else {
588
-			if (isset($this->partial[$file])) {
589
-				return self::PARTIAL;
590
-			} else {
591
-				return self::NOT_FOUND;
592
-			}
593
-		}
594
-	}
595
-
596
-	/**
597
-	 * search for files matching $pattern
598
-	 *
599
-	 * @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
600
-	 * @return ICacheEntry[] an array of cache entries where the name matches the search pattern
601
-	 */
602
-	public function search($pattern) {
603
-		// normalize pattern
604
-		$pattern = $this->normalize($pattern);
605
-
606
-		if ($pattern === '%%') {
607
-			return [];
608
-		}
609
-
610
-
611
-		$sql = '
205
+            $result = $this->connection->executeQuery($sql, [$fileId]);
206
+            $files = $result->fetchAll();
207
+            return array_map(function (array $data) {
208
+                return self::cacheEntryFromData($data, $this->mimetypeLoader);;
209
+            }, $files);
210
+        } else {
211
+            return array();
212
+        }
213
+    }
214
+
215
+    /**
216
+     * insert or update meta data for a file or folder
217
+     *
218
+     * @param string $file
219
+     * @param array $data
220
+     *
221
+     * @return int file id
222
+     * @throws \RuntimeException
223
+     */
224
+    public function put($file, array $data) {
225
+        if (($id = $this->getId($file)) > -1) {
226
+            $this->update($id, $data);
227
+            return $id;
228
+        } else {
229
+            return $this->insert($file, $data);
230
+        }
231
+    }
232
+
233
+    /**
234
+     * insert meta data for a new file or folder
235
+     *
236
+     * @param string $file
237
+     * @param array $data
238
+     *
239
+     * @return int file id
240
+     * @throws \RuntimeException
241
+     */
242
+    public function insert($file, array $data) {
243
+        // normalize file
244
+        $file = $this->normalize($file);
245
+
246
+        if (isset($this->partial[$file])) { //add any saved partial data
247
+            $data = array_merge($this->partial[$file], $data);
248
+            unset($this->partial[$file]);
249
+        }
250
+
251
+        $requiredFields = array('size', 'mtime', 'mimetype');
252
+        foreach ($requiredFields as $field) {
253
+            if (!isset($data[$field])) { //data not complete save as partial and return
254
+                $this->partial[$file] = $data;
255
+                return -1;
256
+            }
257
+        }
258
+
259
+        $data['path'] = $file;
260
+        $data['parent'] = $this->getParentId($file);
261
+        $data['name'] = \OC_Util::basename($file);
262
+
263
+        list($queryParts, $params) = $this->buildParts($data);
264
+        $queryParts[] = '`storage`';
265
+        $params[] = $this->getNumericStorageId();
266
+
267
+        $queryParts = array_map(function ($item) {
268
+            return trim($item, "`");
269
+        }, $queryParts);
270
+        $values = array_combine($queryParts, $params);
271
+        if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [
272
+            'storage',
273
+            'path_hash',
274
+        ])
275
+        ) {
276
+            return (int)$this->connection->lastInsertId('*PREFIX*filecache');
277
+        }
278
+
279
+        // The file was created in the mean time
280
+        if (($id = $this->getId($file)) > -1) {
281
+            $this->update($id, $data);
282
+            return $id;
283
+        } else {
284
+            throw new \RuntimeException('File entry could not be inserted with insertIfNotExist() but could also not be selected with getId() in order to perform an update. Please try again.');
285
+        }
286
+    }
287
+
288
+    /**
289
+     * update the metadata of an existing file or folder in the cache
290
+     *
291
+     * @param int $id the fileid of the existing file or folder
292
+     * @param array $data [$key => $value] the metadata to update, only the fields provided in the array will be updated, non-provided values will remain unchanged
293
+     */
294
+    public function update($id, array $data) {
295
+
296
+        if (isset($data['path'])) {
297
+            // normalize path
298
+            $data['path'] = $this->normalize($data['path']);
299
+        }
300
+
301
+        if (isset($data['name'])) {
302
+            // normalize path
303
+            $data['name'] = $this->normalize($data['name']);
304
+        }
305
+
306
+        list($queryParts, $params) = $this->buildParts($data);
307
+        // duplicate $params because we need the parts twice in the SQL statement
308
+        // once for the SET part, once in the WHERE clause
309
+        $params = array_merge($params, $params);
310
+        $params[] = $id;
311
+
312
+        // don't update if the data we try to set is the same as the one in the record
313
+        // some databases (Postgres) don't like superfluous updates
314
+        $sql = 'UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? ' .
315
+            'WHERE (' .
316
+            implode(' <> ? OR ', $queryParts) . ' <> ? OR ' .
317
+            implode(' IS NULL OR ', $queryParts) . ' IS NULL' .
318
+            ') AND `fileid` = ? ';
319
+        $this->connection->executeQuery($sql, $params);
320
+
321
+    }
322
+
323
+    /**
324
+     * extract query parts and params array from data array
325
+     *
326
+     * @param array $data
327
+     * @return array [$queryParts, $params]
328
+     *        $queryParts: string[], the (escaped) column names to be set in the query
329
+     *        $params: mixed[], the new values for the columns, to be passed as params to the query
330
+     */
331
+    protected function buildParts(array $data) {
332
+        $fields = array(
333
+            'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted',
334
+            'etag', 'permissions', 'checksum');
335
+
336
+        $doNotCopyStorageMTime = false;
337
+        if (array_key_exists('mtime', $data) && $data['mtime'] === null) {
338
+            // this horrific magic tells it to not copy storage_mtime to mtime
339
+            unset($data['mtime']);
340
+            $doNotCopyStorageMTime = true;
341
+        }
342
+
343
+        $params = array();
344
+        $queryParts = array();
345
+        foreach ($data as $name => $value) {
346
+            if (array_search($name, $fields) !== false) {
347
+                if ($name === 'path') {
348
+                    $params[] = md5($value);
349
+                    $queryParts[] = '`path_hash`';
350
+                } elseif ($name === 'mimetype') {
351
+                    $params[] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
352
+                    $queryParts[] = '`mimepart`';
353
+                    $value = $this->mimetypeLoader->getId($value);
354
+                } elseif ($name === 'storage_mtime') {
355
+                    if (!$doNotCopyStorageMTime && !isset($data['mtime'])) {
356
+                        $params[] = $value;
357
+                        $queryParts[] = '`mtime`';
358
+                    }
359
+                } elseif ($name === 'encrypted') {
360
+                    if (isset($data['encryptedVersion'])) {
361
+                        $value = $data['encryptedVersion'];
362
+                    } else {
363
+                        // Boolean to integer conversion
364
+                        $value = $value ? 1 : 0;
365
+                    }
366
+                }
367
+                $params[] = $value;
368
+                $queryParts[] = '`' . $name . '`';
369
+            }
370
+        }
371
+        return array($queryParts, $params);
372
+    }
373
+
374
+    /**
375
+     * get the file id for a file
376
+     *
377
+     * A file id is a numeric id for a file or folder that's unique within an owncloud instance which stays the same for the lifetime of a file
378
+     *
379
+     * File ids are easiest way for apps to store references to a file since unlike paths they are not affected by renames or sharing
380
+     *
381
+     * @param string $file
382
+     * @return int
383
+     */
384
+    public function getId($file) {
385
+        // normalize file
386
+        $file = $this->normalize($file);
387
+
388
+        $pathHash = md5($file);
389
+
390
+        $sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
391
+        $result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
392
+        if ($row = $result->fetch()) {
393
+            return $row['fileid'];
394
+        } else {
395
+            return -1;
396
+        }
397
+    }
398
+
399
+    /**
400
+     * get the id of the parent folder of a file
401
+     *
402
+     * @param string $file
403
+     * @return int
404
+     */
405
+    public function getParentId($file) {
406
+        if ($file === '') {
407
+            return -1;
408
+        } else {
409
+            $parent = $this->getParentPath($file);
410
+            return (int)$this->getId($parent);
411
+        }
412
+    }
413
+
414
+    private function getParentPath($path) {
415
+        $parent = dirname($path);
416
+        if ($parent === '.') {
417
+            $parent = '';
418
+        }
419
+        return $parent;
420
+    }
421
+
422
+    /**
423
+     * check if a file is available in the cache
424
+     *
425
+     * @param string $file
426
+     * @return bool
427
+     */
428
+    public function inCache($file) {
429
+        return $this->getId($file) != -1;
430
+    }
431
+
432
+    /**
433
+     * remove a file or folder from the cache
434
+     *
435
+     * when removing a folder from the cache all files and folders inside the folder will be removed as well
436
+     *
437
+     * @param string $file
438
+     */
439
+    public function remove($file) {
440
+        $entry = $this->get($file);
441
+        $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
442
+        $this->connection->executeQuery($sql, array($entry['fileid']));
443
+        if ($entry['mimetype'] === 'httpd/unix-directory') {
444
+            $this->removeChildren($entry);
445
+        }
446
+    }
447
+
448
+    /**
449
+     * Get all sub folders of a folder
450
+     *
451
+     * @param array $entry the cache entry of the folder to get the subfolders for
452
+     * @return array[] the cache entries for the subfolders
453
+     */
454
+    private function getSubFolders($entry) {
455
+        $children = $this->getFolderContentsById($entry['fileid']);
456
+        return array_filter($children, function ($child) {
457
+            return $child['mimetype'] === 'httpd/unix-directory';
458
+        });
459
+    }
460
+
461
+    /**
462
+     * Recursively remove all children of a folder
463
+     *
464
+     * @param array $entry the cache entry of the folder to remove the children of
465
+     * @throws \OC\DatabaseException
466
+     */
467
+    private function removeChildren($entry) {
468
+        $subFolders = $this->getSubFolders($entry);
469
+        foreach ($subFolders as $folder) {
470
+            $this->removeChildren($folder);
471
+        }
472
+        $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `parent` = ?';
473
+        $this->connection->executeQuery($sql, array($entry['fileid']));
474
+    }
475
+
476
+    /**
477
+     * Move a file or folder in the cache
478
+     *
479
+     * @param string $source
480
+     * @param string $target
481
+     */
482
+    public function move($source, $target) {
483
+        $this->moveFromCache($this, $source, $target);
484
+    }
485
+
486
+    /**
487
+     * Get the storage id and path needed for a move
488
+     *
489
+     * @param string $path
490
+     * @return array [$storageId, $internalPath]
491
+     */
492
+    protected function getMoveInfo($path) {
493
+        return [$this->getNumericStorageId(), $path];
494
+    }
495
+
496
+    /**
497
+     * Move a file or folder in the cache
498
+     *
499
+     * @param \OCP\Files\Cache\ICache $sourceCache
500
+     * @param string $sourcePath
501
+     * @param string $targetPath
502
+     * @throws \OC\DatabaseException
503
+     * @throws \Exception if the given storages have an invalid id
504
+     */
505
+    public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
506
+        if ($sourceCache instanceof Cache) {
507
+            // normalize source and target
508
+            $sourcePath = $this->normalize($sourcePath);
509
+            $targetPath = $this->normalize($targetPath);
510
+
511
+            $sourceData = $sourceCache->get($sourcePath);
512
+            $sourceId = $sourceData['fileid'];
513
+            $newParentId = $this->getParentId($targetPath);
514
+
515
+            list($sourceStorageId, $sourcePath) = $sourceCache->getMoveInfo($sourcePath);
516
+            list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath);
517
+
518
+            if (is_null($sourceStorageId) || $sourceStorageId === false) {
519
+                throw new \Exception('Invalid source storage id: ' . $sourceStorageId);
520
+            }
521
+            if (is_null($targetStorageId) || $targetStorageId === false) {
522
+                throw new \Exception('Invalid target storage id: ' . $targetStorageId);
523
+            }
524
+
525
+            // sql for final update
526
+            $moveSql = 'UPDATE `*PREFIX*filecache` SET `storage` =  ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` =? WHERE `fileid` = ?';
527
+
528
+            if ($sourceData['mimetype'] === 'httpd/unix-directory') {
529
+                //find all child entries
530
+                $sql = 'SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?';
531
+                $result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']);
532
+                $childEntries = $result->fetchAll();
533
+                $sourceLength = strlen($sourcePath);
534
+                $this->connection->beginTransaction();
535
+                $query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
536
+
537
+                foreach ($childEntries as $child) {
538
+                    $newTargetPath = $targetPath . substr($child['path'], $sourceLength);
539
+                    $query->execute([$targetStorageId, $newTargetPath, md5($newTargetPath), $child['fileid']]);
540
+                }
541
+                $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
542
+                $this->connection->commit();
543
+            } else {
544
+                $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), \OC_Util::basename($targetPath), $newParentId, $sourceId]);
545
+            }
546
+        } else {
547
+            $this->moveFromCacheFallback($sourceCache, $sourcePath, $targetPath);
548
+        }
549
+    }
550
+
551
+    /**
552
+     * remove all entries for files that are stored on the storage from the cache
553
+     */
554
+    public function clear() {
555
+        $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `storage` = ?';
556
+        $this->connection->executeQuery($sql, array($this->getNumericStorageId()));
557
+
558
+        $sql = 'DELETE FROM `*PREFIX*storages` WHERE `id` = ?';
559
+        $this->connection->executeQuery($sql, array($this->storageId));
560
+    }
561
+
562
+    /**
563
+     * Get the scan status of a file
564
+     *
565
+     * - Cache::NOT_FOUND: File is not in the cache
566
+     * - Cache::PARTIAL: File is not stored in the cache but some incomplete data is known
567
+     * - Cache::SHALLOW: The folder and it's direct children are in the cache but not all sub folders are fully scanned
568
+     * - Cache::COMPLETE: The file or folder, with all it's children) are fully scanned
569
+     *
570
+     * @param string $file
571
+     *
572
+     * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
573
+     */
574
+    public function getStatus($file) {
575
+        // normalize file
576
+        $file = $this->normalize($file);
577
+
578
+        $pathHash = md5($file);
579
+        $sql = 'SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
580
+        $result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
581
+        if ($row = $result->fetch()) {
582
+            if ((int)$row['size'] === -1) {
583
+                return self::SHALLOW;
584
+            } else {
585
+                return self::COMPLETE;
586
+            }
587
+        } else {
588
+            if (isset($this->partial[$file])) {
589
+                return self::PARTIAL;
590
+            } else {
591
+                return self::NOT_FOUND;
592
+            }
593
+        }
594
+    }
595
+
596
+    /**
597
+     * search for files matching $pattern
598
+     *
599
+     * @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
600
+     * @return ICacheEntry[] an array of cache entries where the name matches the search pattern
601
+     */
602
+    public function search($pattern) {
603
+        // normalize pattern
604
+        $pattern = $this->normalize($pattern);
605
+
606
+        if ($pattern === '%%') {
607
+            return [];
608
+        }
609
+
610
+
611
+        $sql = '
612 612
 			SELECT `fileid`, `storage`, `path`, `parent`, `name`,
613 613
 				`mimetype`, `storage_mtime`, `mimepart`, `size`, `mtime`,
614 614
 				 `encrypted`, `etag`, `permissions`, `checksum`
615 615
 			FROM `*PREFIX*filecache`
616 616
 			WHERE `storage` = ? AND `name` ILIKE ?';
617
-		$result = $this->connection->executeQuery($sql,
618
-			[$this->getNumericStorageId(), $pattern]
619
-		);
620
-
621
-		return $this->searchResultToCacheEntries($result);
622
-	}
623
-
624
-	/**
625
-	 * @param Statement $result
626
-	 * @return CacheEntry[]
627
-	 */
628
-	private function searchResultToCacheEntries(Statement $result) {
629
-		$files = $result->fetchAll();
630
-
631
-		return array_map(function (array $data) {
632
-			return self::cacheEntryFromData($data, $this->mimetypeLoader);
633
-		}, $files);
634
-	}
635
-
636
-	/**
637
-	 * search for files by mimetype
638
-	 *
639
-	 * @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image')
640
-	 *        where it will search for all mimetypes in the group ('image/*')
641
-	 * @return ICacheEntry[] an array of cache entries where the mimetype matches the search
642
-	 */
643
-	public function searchByMime($mimetype) {
644
-		if (strpos($mimetype, '/')) {
645
-			$where = '`mimetype` = ?';
646
-		} else {
647
-			$where = '`mimepart` = ?';
648
-		}
649
-		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `storage_mtime`, `mtime`, `encrypted`, `etag`, `permissions`, `checksum`
617
+        $result = $this->connection->executeQuery($sql,
618
+            [$this->getNumericStorageId(), $pattern]
619
+        );
620
+
621
+        return $this->searchResultToCacheEntries($result);
622
+    }
623
+
624
+    /**
625
+     * @param Statement $result
626
+     * @return CacheEntry[]
627
+     */
628
+    private function searchResultToCacheEntries(Statement $result) {
629
+        $files = $result->fetchAll();
630
+
631
+        return array_map(function (array $data) {
632
+            return self::cacheEntryFromData($data, $this->mimetypeLoader);
633
+        }, $files);
634
+    }
635
+
636
+    /**
637
+     * search for files by mimetype
638
+     *
639
+     * @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image')
640
+     *        where it will search for all mimetypes in the group ('image/*')
641
+     * @return ICacheEntry[] an array of cache entries where the mimetype matches the search
642
+     */
643
+    public function searchByMime($mimetype) {
644
+        if (strpos($mimetype, '/')) {
645
+            $where = '`mimetype` = ?';
646
+        } else {
647
+            $where = '`mimepart` = ?';
648
+        }
649
+        $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `storage_mtime`, `mtime`, `encrypted`, `etag`, `permissions`, `checksum`
650 650
 				FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?';
651
-		$mimetype = $this->mimetypeLoader->getId($mimetype);
652
-		$result = $this->connection->executeQuery($sql, array($mimetype, $this->getNumericStorageId()));
653
-
654
-		return $this->searchResultToCacheEntries($result);
655
-	}
656
-
657
-	public function searchQuery(ISearchQuery $searchQuery) {
658
-		$builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
659
-
660
-		$query = $builder->select(['fileid', 'storage', 'path', 'parent', 'name', 'mimetype', 'mimepart', 'size', 'mtime', 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum'])
661
-			->from('filecache', 'file');
662
-
663
-		$query->where($builder->expr()->eq('storage', $builder->createNamedParameter($this->getNumericStorageId())));
664
-
665
-		if ($this->querySearchHelper->shouldJoinTags($searchQuery->getSearchOperation())) {
666
-			$query
667
-				->innerJoin('file', 'vcategory_to_object', 'tagmap', $builder->expr()->eq('file.fileid', 'tagmap.objid'))
668
-				->innerJoin('tagmap', 'vcategory', 'tag', $builder->expr()->andX(
669
-					$builder->expr()->eq('tagmap.type', 'tag.type'),
670
-					$builder->expr()->eq('tagmap.categoryid', 'tag.id')
671
-				))
672
-				->andWhere($builder->expr()->eq('tag.type', $builder->createNamedParameter('files')))
673
-				->andWhere($builder->expr()->eq('tag.uid', $builder->createNamedParameter($searchQuery->getUser()->getUID())));
674
-		}
675
-
676
-		$query->andWhere($this->querySearchHelper->searchOperatorToDBExpr($builder, $searchQuery->getSearchOperation()));
677
-
678
-		if ($searchQuery->getLimit()) {
679
-			$query->setMaxResults($searchQuery->getLimit());
680
-		}
681
-		if ($searchQuery->getOffset()) {
682
-			$query->setFirstResult($searchQuery->getOffset());
683
-		}
684
-
685
-		$result = $query->execute();
686
-		return $this->searchResultToCacheEntries($result);
687
-	}
688
-
689
-	/**
690
-	 * Search for files by tag of a given users.
691
-	 *
692
-	 * Note that every user can tag files differently.
693
-	 *
694
-	 * @param string|int $tag name or tag id
695
-	 * @param string $userId owner of the tags
696
-	 * @return ICacheEntry[] file data
697
-	 */
698
-	public function searchByTag($tag, $userId) {
699
-		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, ' .
700
-			'`mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, ' .
701
-			'`encrypted`, `etag`, `permissions`, `checksum` ' .
702
-			'FROM `*PREFIX*filecache` `file`, ' .
703
-			'`*PREFIX*vcategory_to_object` `tagmap`, ' .
704
-			'`*PREFIX*vcategory` `tag` ' .
705
-			// JOIN filecache to vcategory_to_object
706
-			'WHERE `file`.`fileid` = `tagmap`.`objid` ' .
707
-			// JOIN vcategory_to_object to vcategory
708
-			'AND `tagmap`.`type` = `tag`.`type` ' .
709
-			'AND `tagmap`.`categoryid` = `tag`.`id` ' .
710
-			// conditions
711
-			'AND `file`.`storage` = ? ' .
712
-			'AND `tag`.`type` = \'files\' ' .
713
-			'AND `tag`.`uid` = ? ';
714
-		if (is_int($tag)) {
715
-			$sql .= 'AND `tag`.`id` = ? ';
716
-		} else {
717
-			$sql .= 'AND `tag`.`category` = ? ';
718
-		}
719
-		$result = $this->connection->executeQuery(
720
-			$sql,
721
-			[
722
-				$this->getNumericStorageId(),
723
-				$userId,
724
-				$tag
725
-			]
726
-		);
727
-
728
-		$files = $result->fetchAll();
729
-
730
-		return array_map(function (array $data) {
731
-			return self::cacheEntryFromData($data, $this->mimetypeLoader);
732
-		}, $files);
733
-	}
734
-
735
-	/**
736
-	 * Re-calculate the folder size and the size of all parent folders
737
-	 *
738
-	 * @param string|boolean $path
739
-	 * @param array $data (optional) meta data of the folder
740
-	 */
741
-	public function correctFolderSize($path, $data = null) {
742
-		$this->calculateFolderSize($path, $data);
743
-		if ($path !== '') {
744
-			$parent = dirname($path);
745
-			if ($parent === '.' or $parent === '/') {
746
-				$parent = '';
747
-			}
748
-			$this->correctFolderSize($parent);
749
-		}
750
-	}
751
-
752
-	/**
753
-	 * calculate the size of a folder and set it in the cache
754
-	 *
755
-	 * @param string $path
756
-	 * @param array $entry (optional) meta data of the folder
757
-	 * @return int
758
-	 */
759
-	public function calculateFolderSize($path, $entry = null) {
760
-		$totalSize = 0;
761
-		if (is_null($entry) or !isset($entry['fileid'])) {
762
-			$entry = $this->get($path);
763
-		}
764
-		if (isset($entry['mimetype']) && $entry['mimetype'] === 'httpd/unix-directory') {
765
-			$id = $entry['fileid'];
766
-			$sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 ' .
767
-				'FROM `*PREFIX*filecache` ' .
768
-				'WHERE `parent` = ? AND `storage` = ?';
769
-			$result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
770
-			if ($row = $result->fetch()) {
771
-				$result->closeCursor();
772
-				list($sum, $min) = array_values($row);
773
-				$sum = 0 + $sum;
774
-				$min = 0 + $min;
775
-				if ($min === -1) {
776
-					$totalSize = $min;
777
-				} else {
778
-					$totalSize = $sum;
779
-				}
780
-				$update = array();
781
-				if ($entry['size'] !== $totalSize) {
782
-					$update['size'] = $totalSize;
783
-				}
784
-				if (count($update) > 0) {
785
-					$this->update($id, $update);
786
-				}
787
-			} else {
788
-				$result->closeCursor();
789
-			}
790
-		}
791
-		return $totalSize;
792
-	}
793
-
794
-	/**
795
-	 * get all file ids on the files on the storage
796
-	 *
797
-	 * @return int[]
798
-	 */
799
-	public function getAll() {
800
-		$sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?';
801
-		$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId()));
802
-		$ids = array();
803
-		while ($row = $result->fetch()) {
804
-			$ids[] = $row['fileid'];
805
-		}
806
-		return $ids;
807
-	}
808
-
809
-	/**
810
-	 * find a folder in the cache which has not been fully scanned
811
-	 *
812
-	 * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
813
-	 * use the one with the highest id gives the best result with the background scanner, since that is most
814
-	 * likely the folder where we stopped scanning previously
815
-	 *
816
-	 * @return string|bool the path of the folder or false when no folder matched
817
-	 */
818
-	public function getIncomplete() {
819
-		$query = $this->connection->prepare('SELECT `path` FROM `*PREFIX*filecache`'
820
-			. ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC', 1);
821
-		$query->execute([$this->getNumericStorageId()]);
822
-		if ($row = $query->fetch()) {
823
-			return $row['path'];
824
-		} else {
825
-			return false;
826
-		}
827
-	}
828
-
829
-	/**
830
-	 * get the path of a file on this storage by it's file id
831
-	 *
832
-	 * @param int $id the file id of the file or folder to search
833
-	 * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache
834
-	 */
835
-	public function getPathById($id) {
836
-		$sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ? AND `storage` = ?';
837
-		$result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
838
-		if ($row = $result->fetch()) {
839
-			// Oracle stores empty strings as null...
840
-			if ($row['path'] === null) {
841
-				return '';
842
-			}
843
-			return $row['path'];
844
-		} else {
845
-			return null;
846
-		}
847
-	}
848
-
849
-	/**
850
-	 * get the storage id of the storage for a file and the internal path of the file
851
-	 * unlike getPathById this does not limit the search to files on this storage and
852
-	 * instead does a global search in the cache table
853
-	 *
854
-	 * @param int $id
855
-	 * @deprecated use getPathById() instead
856
-	 * @return array first element holding the storage id, second the path
857
-	 */
858
-	static public function getById($id) {
859
-		$connection = \OC::$server->getDatabaseConnection();
860
-		$sql = 'SELECT `storage`, `path` FROM `*PREFIX*filecache` WHERE `fileid` = ?';
861
-		$result = $connection->executeQuery($sql, array($id));
862
-		if ($row = $result->fetch()) {
863
-			$numericId = $row['storage'];
864
-			$path = $row['path'];
865
-		} else {
866
-			return null;
867
-		}
868
-
869
-		if ($id = Storage::getStorageId($numericId)) {
870
-			return array($id, $path);
871
-		} else {
872
-			return null;
873
-		}
874
-	}
875
-
876
-	/**
877
-	 * normalize the given path
878
-	 *
879
-	 * @param string $path
880
-	 * @return string
881
-	 */
882
-	public function normalize($path) {
883
-
884
-		return trim(\OC_Util::normalizeUnicode($path), '/');
885
-	}
651
+        $mimetype = $this->mimetypeLoader->getId($mimetype);
652
+        $result = $this->connection->executeQuery($sql, array($mimetype, $this->getNumericStorageId()));
653
+
654
+        return $this->searchResultToCacheEntries($result);
655
+    }
656
+
657
+    public function searchQuery(ISearchQuery $searchQuery) {
658
+        $builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
659
+
660
+        $query = $builder->select(['fileid', 'storage', 'path', 'parent', 'name', 'mimetype', 'mimepart', 'size', 'mtime', 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum'])
661
+            ->from('filecache', 'file');
662
+
663
+        $query->where($builder->expr()->eq('storage', $builder->createNamedParameter($this->getNumericStorageId())));
664
+
665
+        if ($this->querySearchHelper->shouldJoinTags($searchQuery->getSearchOperation())) {
666
+            $query
667
+                ->innerJoin('file', 'vcategory_to_object', 'tagmap', $builder->expr()->eq('file.fileid', 'tagmap.objid'))
668
+                ->innerJoin('tagmap', 'vcategory', 'tag', $builder->expr()->andX(
669
+                    $builder->expr()->eq('tagmap.type', 'tag.type'),
670
+                    $builder->expr()->eq('tagmap.categoryid', 'tag.id')
671
+                ))
672
+                ->andWhere($builder->expr()->eq('tag.type', $builder->createNamedParameter('files')))
673
+                ->andWhere($builder->expr()->eq('tag.uid', $builder->createNamedParameter($searchQuery->getUser()->getUID())));
674
+        }
675
+
676
+        $query->andWhere($this->querySearchHelper->searchOperatorToDBExpr($builder, $searchQuery->getSearchOperation()));
677
+
678
+        if ($searchQuery->getLimit()) {
679
+            $query->setMaxResults($searchQuery->getLimit());
680
+        }
681
+        if ($searchQuery->getOffset()) {
682
+            $query->setFirstResult($searchQuery->getOffset());
683
+        }
684
+
685
+        $result = $query->execute();
686
+        return $this->searchResultToCacheEntries($result);
687
+    }
688
+
689
+    /**
690
+     * Search for files by tag of a given users.
691
+     *
692
+     * Note that every user can tag files differently.
693
+     *
694
+     * @param string|int $tag name or tag id
695
+     * @param string $userId owner of the tags
696
+     * @return ICacheEntry[] file data
697
+     */
698
+    public function searchByTag($tag, $userId) {
699
+        $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, ' .
700
+            '`mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, ' .
701
+            '`encrypted`, `etag`, `permissions`, `checksum` ' .
702
+            'FROM `*PREFIX*filecache` `file`, ' .
703
+            '`*PREFIX*vcategory_to_object` `tagmap`, ' .
704
+            '`*PREFIX*vcategory` `tag` ' .
705
+            // JOIN filecache to vcategory_to_object
706
+            'WHERE `file`.`fileid` = `tagmap`.`objid` ' .
707
+            // JOIN vcategory_to_object to vcategory
708
+            'AND `tagmap`.`type` = `tag`.`type` ' .
709
+            'AND `tagmap`.`categoryid` = `tag`.`id` ' .
710
+            // conditions
711
+            'AND `file`.`storage` = ? ' .
712
+            'AND `tag`.`type` = \'files\' ' .
713
+            'AND `tag`.`uid` = ? ';
714
+        if (is_int($tag)) {
715
+            $sql .= 'AND `tag`.`id` = ? ';
716
+        } else {
717
+            $sql .= 'AND `tag`.`category` = ? ';
718
+        }
719
+        $result = $this->connection->executeQuery(
720
+            $sql,
721
+            [
722
+                $this->getNumericStorageId(),
723
+                $userId,
724
+                $tag
725
+            ]
726
+        );
727
+
728
+        $files = $result->fetchAll();
729
+
730
+        return array_map(function (array $data) {
731
+            return self::cacheEntryFromData($data, $this->mimetypeLoader);
732
+        }, $files);
733
+    }
734
+
735
+    /**
736
+     * Re-calculate the folder size and the size of all parent folders
737
+     *
738
+     * @param string|boolean $path
739
+     * @param array $data (optional) meta data of the folder
740
+     */
741
+    public function correctFolderSize($path, $data = null) {
742
+        $this->calculateFolderSize($path, $data);
743
+        if ($path !== '') {
744
+            $parent = dirname($path);
745
+            if ($parent === '.' or $parent === '/') {
746
+                $parent = '';
747
+            }
748
+            $this->correctFolderSize($parent);
749
+        }
750
+    }
751
+
752
+    /**
753
+     * calculate the size of a folder and set it in the cache
754
+     *
755
+     * @param string $path
756
+     * @param array $entry (optional) meta data of the folder
757
+     * @return int
758
+     */
759
+    public function calculateFolderSize($path, $entry = null) {
760
+        $totalSize = 0;
761
+        if (is_null($entry) or !isset($entry['fileid'])) {
762
+            $entry = $this->get($path);
763
+        }
764
+        if (isset($entry['mimetype']) && $entry['mimetype'] === 'httpd/unix-directory') {
765
+            $id = $entry['fileid'];
766
+            $sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 ' .
767
+                'FROM `*PREFIX*filecache` ' .
768
+                'WHERE `parent` = ? AND `storage` = ?';
769
+            $result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
770
+            if ($row = $result->fetch()) {
771
+                $result->closeCursor();
772
+                list($sum, $min) = array_values($row);
773
+                $sum = 0 + $sum;
774
+                $min = 0 + $min;
775
+                if ($min === -1) {
776
+                    $totalSize = $min;
777
+                } else {
778
+                    $totalSize = $sum;
779
+                }
780
+                $update = array();
781
+                if ($entry['size'] !== $totalSize) {
782
+                    $update['size'] = $totalSize;
783
+                }
784
+                if (count($update) > 0) {
785
+                    $this->update($id, $update);
786
+                }
787
+            } else {
788
+                $result->closeCursor();
789
+            }
790
+        }
791
+        return $totalSize;
792
+    }
793
+
794
+    /**
795
+     * get all file ids on the files on the storage
796
+     *
797
+     * @return int[]
798
+     */
799
+    public function getAll() {
800
+        $sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?';
801
+        $result = $this->connection->executeQuery($sql, array($this->getNumericStorageId()));
802
+        $ids = array();
803
+        while ($row = $result->fetch()) {
804
+            $ids[] = $row['fileid'];
805
+        }
806
+        return $ids;
807
+    }
808
+
809
+    /**
810
+     * find a folder in the cache which has not been fully scanned
811
+     *
812
+     * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
813
+     * use the one with the highest id gives the best result with the background scanner, since that is most
814
+     * likely the folder where we stopped scanning previously
815
+     *
816
+     * @return string|bool the path of the folder or false when no folder matched
817
+     */
818
+    public function getIncomplete() {
819
+        $query = $this->connection->prepare('SELECT `path` FROM `*PREFIX*filecache`'
820
+            . ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC', 1);
821
+        $query->execute([$this->getNumericStorageId()]);
822
+        if ($row = $query->fetch()) {
823
+            return $row['path'];
824
+        } else {
825
+            return false;
826
+        }
827
+    }
828
+
829
+    /**
830
+     * get the path of a file on this storage by it's file id
831
+     *
832
+     * @param int $id the file id of the file or folder to search
833
+     * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache
834
+     */
835
+    public function getPathById($id) {
836
+        $sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ? AND `storage` = ?';
837
+        $result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
838
+        if ($row = $result->fetch()) {
839
+            // Oracle stores empty strings as null...
840
+            if ($row['path'] === null) {
841
+                return '';
842
+            }
843
+            return $row['path'];
844
+        } else {
845
+            return null;
846
+        }
847
+    }
848
+
849
+    /**
850
+     * get the storage id of the storage for a file and the internal path of the file
851
+     * unlike getPathById this does not limit the search to files on this storage and
852
+     * instead does a global search in the cache table
853
+     *
854
+     * @param int $id
855
+     * @deprecated use getPathById() instead
856
+     * @return array first element holding the storage id, second the path
857
+     */
858
+    static public function getById($id) {
859
+        $connection = \OC::$server->getDatabaseConnection();
860
+        $sql = 'SELECT `storage`, `path` FROM `*PREFIX*filecache` WHERE `fileid` = ?';
861
+        $result = $connection->executeQuery($sql, array($id));
862
+        if ($row = $result->fetch()) {
863
+            $numericId = $row['storage'];
864
+            $path = $row['path'];
865
+        } else {
866
+            return null;
867
+        }
868
+
869
+        if ($id = Storage::getStorageId($numericId)) {
870
+            return array($id, $path);
871
+        } else {
872
+            return null;
873
+        }
874
+    }
875
+
876
+    /**
877
+     * normalize the given path
878
+     *
879
+     * @param string $path
880
+     * @return string
881
+     */
882
+    public function normalize($path) {
883
+
884
+        return trim(\OC_Util::normalizeUnicode($path), '/');
885
+    }
886 886
 }
Please login to merge, or discard this patch.
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -162,21 +162,21 @@  discard block
 block discarded – undo
162 162
 	 */
163 163
 	public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) {
164 164
 		//fix types
165
-		$data['fileid'] = (int)$data['fileid'];
166
-		$data['parent'] = (int)$data['parent'];
165
+		$data['fileid'] = (int) $data['fileid'];
166
+		$data['parent'] = (int) $data['parent'];
167 167
 		$data['size'] = 0 + $data['size'];
168
-		$data['mtime'] = (int)$data['mtime'];
169
-		$data['storage_mtime'] = (int)$data['storage_mtime'];
170
-		$data['encryptedVersion'] = (int)$data['encrypted'];
171
-		$data['encrypted'] = (bool)$data['encrypted'];
168
+		$data['mtime'] = (int) $data['mtime'];
169
+		$data['storage_mtime'] = (int) $data['storage_mtime'];
170
+		$data['encryptedVersion'] = (int) $data['encrypted'];
171
+		$data['encrypted'] = (bool) $data['encrypted'];
172 172
 		$data['storage_id'] = $data['storage'];
173
-		$data['storage'] = (int)$data['storage'];
173
+		$data['storage'] = (int) $data['storage'];
174 174
 		$data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
175 175
 		$data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
176 176
 		if ($data['storage_mtime'] == 0) {
177 177
 			$data['storage_mtime'] = $data['mtime'];
178 178
 		}
179
-		$data['permissions'] = (int)$data['permissions'];
179
+		$data['permissions'] = (int) $data['permissions'];
180 180
 		return new CacheEntry($data);
181 181
 	}
182 182
 
@@ -204,8 +204,8 @@  discard block
 block discarded – undo
204 204
 					FROM `*PREFIX*filecache` WHERE `parent` = ? ORDER BY `name` ASC';
205 205
 			$result = $this->connection->executeQuery($sql, [$fileId]);
206 206
 			$files = $result->fetchAll();
207
-			return array_map(function (array $data) {
208
-				return self::cacheEntryFromData($data, $this->mimetypeLoader);;
207
+			return array_map(function(array $data) {
208
+				return self::cacheEntryFromData($data, $this->mimetypeLoader); ;
209 209
 			}, $files);
210 210
 		} else {
211 211
 			return array();
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
 		$queryParts[] = '`storage`';
265 265
 		$params[] = $this->getNumericStorageId();
266 266
 
267
-		$queryParts = array_map(function ($item) {
267
+		$queryParts = array_map(function($item) {
268 268
 			return trim($item, "`");
269 269
 		}, $queryParts);
270 270
 		$values = array_combine($queryParts, $params);
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
 			'path_hash',
274 274
 		])
275 275
 		) {
276
-			return (int)$this->connection->lastInsertId('*PREFIX*filecache');
276
+			return (int) $this->connection->lastInsertId('*PREFIX*filecache');
277 277
 		}
278 278
 
279 279
 		// The file was created in the mean time
@@ -311,10 +311,10 @@  discard block
 block discarded – undo
311 311
 
312 312
 		// don't update if the data we try to set is the same as the one in the record
313 313
 		// some databases (Postgres) don't like superfluous updates
314
-		$sql = 'UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? ' .
315
-			'WHERE (' .
316
-			implode(' <> ? OR ', $queryParts) . ' <> ? OR ' .
317
-			implode(' IS NULL OR ', $queryParts) . ' IS NULL' .
314
+		$sql = 'UPDATE `*PREFIX*filecache` SET '.implode(' = ?, ', $queryParts).'=? '.
315
+			'WHERE ('.
316
+			implode(' <> ? OR ', $queryParts).' <> ? OR '.
317
+			implode(' IS NULL OR ', $queryParts).' IS NULL'.
318 318
 			') AND `fileid` = ? ';
319 319
 		$this->connection->executeQuery($sql, $params);
320 320
 
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 					}
366 366
 				}
367 367
 				$params[] = $value;
368
-				$queryParts[] = '`' . $name . '`';
368
+				$queryParts[] = '`'.$name.'`';
369 369
 			}
370 370
 		}
371 371
 		return array($queryParts, $params);
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
 			return -1;
408 408
 		} else {
409 409
 			$parent = $this->getParentPath($file);
410
-			return (int)$this->getId($parent);
410
+			return (int) $this->getId($parent);
411 411
 		}
412 412
 	}
413 413
 
@@ -453,7 +453,7 @@  discard block
 block discarded – undo
453 453
 	 */
454 454
 	private function getSubFolders($entry) {
455 455
 		$children = $this->getFolderContentsById($entry['fileid']);
456
-		return array_filter($children, function ($child) {
456
+		return array_filter($children, function($child) {
457 457
 			return $child['mimetype'] === 'httpd/unix-directory';
458 458
 		});
459 459
 	}
@@ -516,10 +516,10 @@  discard block
 block discarded – undo
516 516
 			list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath);
517 517
 
518 518
 			if (is_null($sourceStorageId) || $sourceStorageId === false) {
519
-				throw new \Exception('Invalid source storage id: ' . $sourceStorageId);
519
+				throw new \Exception('Invalid source storage id: '.$sourceStorageId);
520 520
 			}
521 521
 			if (is_null($targetStorageId) || $targetStorageId === false) {
522
-				throw new \Exception('Invalid target storage id: ' . $targetStorageId);
522
+				throw new \Exception('Invalid target storage id: '.$targetStorageId);
523 523
 			}
524 524
 
525 525
 			// sql for final update
@@ -528,14 +528,14 @@  discard block
 block discarded – undo
528 528
 			if ($sourceData['mimetype'] === 'httpd/unix-directory') {
529 529
 				//find all child entries
530 530
 				$sql = 'SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?';
531
-				$result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']);
531
+				$result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath).'/%']);
532 532
 				$childEntries = $result->fetchAll();
533 533
 				$sourceLength = strlen($sourcePath);
534 534
 				$this->connection->beginTransaction();
535 535
 				$query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
536 536
 
537 537
 				foreach ($childEntries as $child) {
538
-					$newTargetPath = $targetPath . substr($child['path'], $sourceLength);
538
+					$newTargetPath = $targetPath.substr($child['path'], $sourceLength);
539 539
 					$query->execute([$targetStorageId, $newTargetPath, md5($newTargetPath), $child['fileid']]);
540 540
 				}
541 541
 				$this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
@@ -579,7 +579,7 @@  discard block
 block discarded – undo
579 579
 		$sql = 'SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
580 580
 		$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
581 581
 		if ($row = $result->fetch()) {
582
-			if ((int)$row['size'] === -1) {
582
+			if ((int) $row['size'] === -1) {
583 583
 				return self::SHALLOW;
584 584
 			} else {
585 585
 				return self::COMPLETE;
@@ -628,7 +628,7 @@  discard block
 block discarded – undo
628 628
 	private function searchResultToCacheEntries(Statement $result) {
629 629
 		$files = $result->fetchAll();
630 630
 
631
-		return array_map(function (array $data) {
631
+		return array_map(function(array $data) {
632 632
 			return self::cacheEntryFromData($data, $this->mimetypeLoader);
633 633
 		}, $files);
634 634
 	}
@@ -647,7 +647,7 @@  discard block
 block discarded – undo
647 647
 			$where = '`mimepart` = ?';
648 648
 		}
649 649
 		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `storage_mtime`, `mtime`, `encrypted`, `etag`, `permissions`, `checksum`
650
-				FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?';
650
+				FROM `*PREFIX*filecache` WHERE ' . $where.' AND `storage` = ?';
651 651
 		$mimetype = $this->mimetypeLoader->getId($mimetype);
652 652
 		$result = $this->connection->executeQuery($sql, array($mimetype, $this->getNumericStorageId()));
653 653
 
@@ -696,20 +696,20 @@  discard block
 block discarded – undo
696 696
 	 * @return ICacheEntry[] file data
697 697
 	 */
698 698
 	public function searchByTag($tag, $userId) {
699
-		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, ' .
700
-			'`mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, ' .
701
-			'`encrypted`, `etag`, `permissions`, `checksum` ' .
702
-			'FROM `*PREFIX*filecache` `file`, ' .
703
-			'`*PREFIX*vcategory_to_object` `tagmap`, ' .
704
-			'`*PREFIX*vcategory` `tag` ' .
699
+		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, '.
700
+			'`mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, '.
701
+			'`encrypted`, `etag`, `permissions`, `checksum` '.
702
+			'FROM `*PREFIX*filecache` `file`, '.
703
+			'`*PREFIX*vcategory_to_object` `tagmap`, '.
704
+			'`*PREFIX*vcategory` `tag` '.
705 705
 			// JOIN filecache to vcategory_to_object
706
-			'WHERE `file`.`fileid` = `tagmap`.`objid` ' .
706
+			'WHERE `file`.`fileid` = `tagmap`.`objid` '.
707 707
 			// JOIN vcategory_to_object to vcategory
708
-			'AND `tagmap`.`type` = `tag`.`type` ' .
709
-			'AND `tagmap`.`categoryid` = `tag`.`id` ' .
708
+			'AND `tagmap`.`type` = `tag`.`type` '.
709
+			'AND `tagmap`.`categoryid` = `tag`.`id` '.
710 710
 			// conditions
711
-			'AND `file`.`storage` = ? ' .
712
-			'AND `tag`.`type` = \'files\' ' .
711
+			'AND `file`.`storage` = ? '.
712
+			'AND `tag`.`type` = \'files\' '.
713 713
 			'AND `tag`.`uid` = ? ';
714 714
 		if (is_int($tag)) {
715 715
 			$sql .= 'AND `tag`.`id` = ? ';
@@ -727,7 +727,7 @@  discard block
 block discarded – undo
727 727
 
728 728
 		$files = $result->fetchAll();
729 729
 
730
-		return array_map(function (array $data) {
730
+		return array_map(function(array $data) {
731 731
 			return self::cacheEntryFromData($data, $this->mimetypeLoader);
732 732
 		}, $files);
733 733
 	}
@@ -763,8 +763,8 @@  discard block
 block discarded – undo
763 763
 		}
764 764
 		if (isset($entry['mimetype']) && $entry['mimetype'] === 'httpd/unix-directory') {
765 765
 			$id = $entry['fileid'];
766
-			$sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 ' .
767
-				'FROM `*PREFIX*filecache` ' .
766
+			$sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 '.
767
+				'FROM `*PREFIX*filecache` '.
768 768
 				'WHERE `parent` = ? AND `storage` = ?';
769 769
 			$result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
770 770
 			if ($row = $result->fetch()) {
Please login to merge, or discard this patch.