Passed
Push — master ( 66c33f...c1ba14 )
by Joas
13:58 queued 21s
created
lib/private/Files/Node/Folder.php 2 patches
Indentation   +425 added lines, -425 removed lines patch added patch discarded remove patch
@@ -50,429 +50,429 @@
 block discarded – undo
50 50
 use OCP\IUserManager;
51 51
 
52 52
 class Folder extends Node implements \OCP\Files\Folder {
53
-	/**
54
-	 * Creates a Folder that represents a non-existing path
55
-	 *
56
-	 * @param string $path path
57
-	 * @return string non-existing node class
58
-	 */
59
-	protected function createNonExistingNode($path) {
60
-		return new NonExistingFolder($this->root, $this->view, $path);
61
-	}
62
-
63
-	/**
64
-	 * @param string $path path relative to the folder
65
-	 * @return string
66
-	 * @throws \OCP\Files\NotPermittedException
67
-	 */
68
-	public function getFullPath($path) {
69
-		$path = $this->normalizePath($path);
70
-		if (!$this->isValidPath($path)) {
71
-			throw new NotPermittedException('Invalid path');
72
-		}
73
-		return $this->path . $path;
74
-	}
75
-
76
-	/**
77
-	 * @param string $path
78
-	 * @return string|null
79
-	 */
80
-	public function getRelativePath($path) {
81
-		return PathHelper::getRelativePath($this->getPath(), $path);
82
-	}
83
-
84
-	/**
85
-	 * check if a node is a (grand-)child of the folder
86
-	 *
87
-	 * @param \OC\Files\Node\Node $node
88
-	 * @return bool
89
-	 */
90
-	public function isSubNode($node) {
91
-		return strpos($node->getPath(), $this->path . '/') === 0;
92
-	}
93
-
94
-	/**
95
-	 * get the content of this directory
96
-	 *
97
-	 * @return Node[]
98
-	 * @throws \OCP\Files\NotFoundException
99
-	 */
100
-	public function getDirectoryListing() {
101
-		$folderContent = $this->view->getDirectoryContent($this->path, '', $this->getFileInfo());
102
-
103
-		return array_map(function (FileInfo $info) {
104
-			if ($info->getMimetype() === FileInfo::MIMETYPE_FOLDER) {
105
-				return new Folder($this->root, $this->view, $info->getPath(), $info, $this);
106
-			} else {
107
-				return new File($this->root, $this->view, $info->getPath(), $info, $this);
108
-			}
109
-		}, $folderContent);
110
-	}
111
-
112
-	/**
113
-	 * @param string $path
114
-	 * @param FileInfo $info
115
-	 * @return File|Folder
116
-	 */
117
-	protected function createNode($path, FileInfo $info = null) {
118
-		if (is_null($info)) {
119
-			$isDir = $this->view->is_dir($path);
120
-		} else {
121
-			$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
122
-		}
123
-		$parent = dirname($path) === $this->getPath() ? $this : null;
124
-		if ($isDir) {
125
-			return new Folder($this->root, $this->view, $path, $info, $parent);
126
-		} else {
127
-			return new File($this->root, $this->view, $path, $info, $parent);
128
-		}
129
-	}
130
-
131
-	/**
132
-	 * Get the node at $path
133
-	 *
134
-	 * @param string $path
135
-	 * @return \OC\Files\Node\Node
136
-	 * @throws \OCP\Files\NotFoundException
137
-	 */
138
-	public function get($path) {
139
-		return $this->root->get($this->getFullPath($path));
140
-	}
141
-
142
-	/**
143
-	 * @param string $path
144
-	 * @return bool
145
-	 */
146
-	public function nodeExists($path) {
147
-		try {
148
-			$this->get($path);
149
-			return true;
150
-		} catch (NotFoundException $e) {
151
-			return false;
152
-		}
153
-	}
154
-
155
-	/**
156
-	 * @param string $path
157
-	 * @return \OC\Files\Node\Folder
158
-	 * @throws \OCP\Files\NotPermittedException
159
-	 */
160
-	public function newFolder($path) {
161
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
162
-			$fullPath = $this->getFullPath($path);
163
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
164
-			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
165
-			if (!$this->view->mkdir($fullPath)) {
166
-				throw new NotPermittedException('Could not create folder');
167
-			}
168
-			$parent = dirname($fullPath) === $this->getPath() ? $this : null;
169
-			$node = new Folder($this->root, $this->view, $fullPath, null, $parent);
170
-			$this->sendHooks(['postWrite', 'postCreate'], [$node]);
171
-			return $node;
172
-		} else {
173
-			throw new NotPermittedException('No create permission for folder');
174
-		}
175
-	}
176
-
177
-	/**
178
-	 * @param string $path
179
-	 * @param string | resource | null $content
180
-	 * @return \OC\Files\Node\File
181
-	 * @throws \OCP\Files\NotPermittedException
182
-	 */
183
-	public function newFile($path, $content = null) {
184
-		if (empty($path)) {
185
-			throw new NotPermittedException('Could not create as provided path is empty');
186
-		}
187
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
188
-			$fullPath = $this->getFullPath($path);
189
-			$nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
190
-			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
191
-			if ($content !== null) {
192
-				$result = $this->view->file_put_contents($fullPath, $content);
193
-			} else {
194
-				$result = $this->view->touch($fullPath);
195
-			}
196
-			if ($result === false) {
197
-				throw new NotPermittedException('Could not create path');
198
-			}
199
-			$node = new File($this->root, $this->view, $fullPath, null, $this);
200
-			$this->sendHooks(['postWrite', 'postCreate'], [$node]);
201
-			return $node;
202
-		}
203
-		throw new NotPermittedException('No create permission for path');
204
-	}
205
-
206
-	private function queryFromOperator(ISearchOperator $operator, string $uid = null): ISearchQuery {
207
-		if ($uid === null) {
208
-			$user = null;
209
-		} else {
210
-			/** @var IUserManager $userManager */
211
-			$userManager = \OC::$server->query(IUserManager::class);
212
-			$user = $userManager->get($uid);
213
-		}
214
-		return new SearchQuery($operator, 0, 0, [], $user);
215
-	}
216
-
217
-	/**
218
-	 * search for files with the name matching $query
219
-	 *
220
-	 * @param string|ISearchQuery $query
221
-	 * @return \OC\Files\Node\Node[]
222
-	 */
223
-	public function search($query) {
224
-		if (is_string($query)) {
225
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
226
-		}
227
-
228
-		// search is handled by a single query covering all caches that this folder contains
229
-		// this is done by collect
230
-
231
-		$limitToHome = $query->limitToHome();
232
-		if ($limitToHome && count(explode('/', $this->path)) !== 3) {
233
-			throw new \InvalidArgumentException('searching by owner is only allows on the users home folder');
234
-		}
235
-
236
-		$rootLength = strlen($this->path);
237
-		$mount = $this->root->getMount($this->path);
238
-		$storage = $mount->getStorage();
239
-		$internalPath = $mount->getInternalPath($this->path);
240
-
241
-		// collect all caches for this folder, indexed by their mountpoint relative to this folder
242
-		// and save the mount which is needed later to construct the FileInfo objects
243
-
244
-		if ($internalPath !== '') {
245
-			// a temporary CacheJail is used to handle filtering down the results to within this folder
246
-			$caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
247
-		} else {
248
-			$caches = ['' => $storage->getCache('')];
249
-		}
250
-		$mountByMountPoint = ['' => $mount];
251
-
252
-		if (!$limitToHome) {
253
-			$mounts = $this->root->getMountsIn($this->path);
254
-			foreach ($mounts as $mount) {
255
-				$storage = $mount->getStorage();
256
-				if ($storage) {
257
-					$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
258
-					$caches[$relativeMountPoint] = $storage->getCache('');
259
-					$mountByMountPoint[$relativeMountPoint] = $mount;
260
-				}
261
-			}
262
-		}
263
-
264
-		/** @var QuerySearchHelper $searchHelper */
265
-		$searchHelper = \OC::$server->get(QuerySearchHelper::class);
266
-		$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
267
-
268
-		// loop through all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
269
-		$files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
270
-			$mount = $mountByMountPoint[$relativeMountPoint];
271
-			return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
272
-				return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
273
-			}, $results);
274
-		}, array_values($resultsPerCache), array_keys($resultsPerCache)));
275
-
276
-		// don't include this folder in the results
277
-		$files = array_filter($files, function (FileInfo $file) {
278
-			return $file->getPath() !== $this->getPath();
279
-		});
280
-
281
-		// since results were returned per-cache, they are no longer fully sorted
282
-		$order = $query->getOrder();
283
-		if ($order) {
284
-			usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
285
-				foreach ($order as $orderField) {
286
-					$cmp = $orderField->sortFileInfo($a, $b);
287
-					if ($cmp !== 0) {
288
-						return $cmp;
289
-					}
290
-				}
291
-				return 0;
292
-			});
293
-		}
294
-
295
-		return array_map(function (FileInfo $file) {
296
-			return $this->createNode($file->getPath(), $file);
297
-		}, $files);
298
-	}
299
-
300
-	private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
301
-		$cacheEntry['internalPath'] = $cacheEntry['path'];
302
-		$cacheEntry['path'] = rtrim($appendRoot . $cacheEntry->getPath(), '/');
303
-		$subPath = $cacheEntry['path'] !== '' ? '/' . $cacheEntry['path'] : '';
304
-		return new \OC\Files\FileInfo($this->path . $subPath, $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
305
-	}
306
-
307
-	/**
308
-	 * search for files by mimetype
309
-	 *
310
-	 * @param string $mimetype
311
-	 * @return Node[]
312
-	 */
313
-	public function searchByMime($mimetype) {
314
-		if (strpos($mimetype, '/') === false) {
315
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
316
-		} else {
317
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
318
-		}
319
-		return $this->search($query);
320
-	}
321
-
322
-	/**
323
-	 * search for files by tag
324
-	 *
325
-	 * @param string|int $tag name or tag id
326
-	 * @param string $userId owner of the tags
327
-	 * @return Node[]
328
-	 */
329
-	public function searchByTag($tag, $userId) {
330
-		$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', $tag), $userId);
331
-		return $this->search($query);
332
-	}
333
-
334
-	/**
335
-	 * @param int $id
336
-	 * @return \OC\Files\Node\Node[]
337
-	 */
338
-	public function getById($id) {
339
-		return $this->root->getByIdInPath((int)$id, $this->getPath());
340
-	}
341
-
342
-	protected function getAppDataDirectoryName(): string {
343
-		$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
344
-		return 'appdata_' . $instanceId;
345
-	}
346
-
347
-	/**
348
-	 * In case the path we are currently in is inside the appdata_* folder,
349
-	 * the original getById method does not work, because it can only look inside
350
-	 * the user's mount points. But the user has no mount point for the root storage.
351
-	 *
352
-	 * So in that case we directly check the mount of the root if it contains
353
-	 * the id. If it does we check if the path is inside the path we are working
354
-	 * in.
355
-	 *
356
-	 * @param int $id
357
-	 * @return array
358
-	 */
359
-	protected function getByIdInRootMount(int $id): array {
360
-		$mount = $this->root->getMount('');
361
-		$cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
362
-		if (!$cacheEntry) {
363
-			return [];
364
-		}
365
-
366
-		$absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
367
-		$currentPath = rtrim($this->path, '/') . '/';
368
-
369
-		if (strpos($absolutePath, $currentPath) !== 0) {
370
-			return [];
371
-		}
372
-
373
-		return [$this->root->createNode(
374
-			$absolutePath, new \OC\Files\FileInfo(
375
-				$absolutePath,
376
-				$mount->getStorage(),
377
-				$cacheEntry->getPath(),
378
-				$cacheEntry,
379
-				$mount
380
-			))];
381
-	}
382
-
383
-	public function getFreeSpace() {
384
-		return $this->view->free_space($this->path);
385
-	}
386
-
387
-	public function delete() {
388
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
389
-			$this->sendHooks(['preDelete']);
390
-			$fileInfo = $this->getFileInfo();
391
-			$this->view->rmdir($this->path);
392
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
393
-			$this->sendHooks(['postDelete'], [$nonExisting]);
394
-		} else {
395
-			throw new NotPermittedException('No delete permission for path');
396
-		}
397
-	}
398
-
399
-	/**
400
-	 * Add a suffix to the name in case the file exists
401
-	 *
402
-	 * @param string $name
403
-	 * @return string
404
-	 * @throws NotPermittedException
405
-	 */
406
-	public function getNonExistingName($name) {
407
-		$uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
408
-		return trim($this->getRelativePath($uniqueName), '/');
409
-	}
410
-
411
-	/**
412
-	 * @param int $limit
413
-	 * @param int $offset
414
-	 * @return \OCP\Files\Node[]
415
-	 */
416
-	public function getRecent($limit, $offset = 0) {
417
-		$filterOutNonEmptyFolder = new SearchBinaryOperator(
418
-			// filter out non empty folders
419
-			ISearchBinaryOperator::OPERATOR_OR,
420
-			[
421
-				new SearchBinaryOperator(
422
-					ISearchBinaryOperator::OPERATOR_NOT,
423
-					[
424
-						new SearchComparison(
425
-							ISearchComparison::COMPARE_EQUAL,
426
-							'mimetype',
427
-							FileInfo::MIMETYPE_FOLDER
428
-						),
429
-					]
430
-				),
431
-				new SearchComparison(
432
-					ISearchComparison::COMPARE_EQUAL,
433
-					'size',
434
-					0
435
-				),
436
-			]
437
-		);
438
-
439
-		$filterNonRecentFiles = new SearchComparison(
440
-			ISearchComparison::COMPARE_GREATER_THAN,
441
-			'mtime',
442
-			strtotime("-2 week")
443
-		);
444
-		if ($offset === 0 && $limit <= 100) {
445
-			$query = new SearchQuery(
446
-				new SearchBinaryOperator(
447
-					ISearchBinaryOperator::OPERATOR_AND,
448
-					[
449
-						$filterOutNonEmptyFolder,
450
-						$filterNonRecentFiles,
451
-					],
452
-				),
453
-				$limit,
454
-				$offset,
455
-				[
456
-					new SearchOrder(
457
-						ISearchOrder::DIRECTION_DESCENDING,
458
-						'mtime'
459
-					),
460
-				]
461
-			);
462
-		} else {
463
-			$query = new SearchQuery(
464
-				$filterOutNonEmptyFolder,
465
-				$limit,
466
-				$offset,
467
-				[
468
-					new SearchOrder(
469
-						ISearchOrder::DIRECTION_DESCENDING,
470
-						'mtime'
471
-					),
472
-				]
473
-			);
474
-		}
475
-
476
-		return $this->search($query);
477
-	}
53
+    /**
54
+     * Creates a Folder that represents a non-existing path
55
+     *
56
+     * @param string $path path
57
+     * @return string non-existing node class
58
+     */
59
+    protected function createNonExistingNode($path) {
60
+        return new NonExistingFolder($this->root, $this->view, $path);
61
+    }
62
+
63
+    /**
64
+     * @param string $path path relative to the folder
65
+     * @return string
66
+     * @throws \OCP\Files\NotPermittedException
67
+     */
68
+    public function getFullPath($path) {
69
+        $path = $this->normalizePath($path);
70
+        if (!$this->isValidPath($path)) {
71
+            throw new NotPermittedException('Invalid path');
72
+        }
73
+        return $this->path . $path;
74
+    }
75
+
76
+    /**
77
+     * @param string $path
78
+     * @return string|null
79
+     */
80
+    public function getRelativePath($path) {
81
+        return PathHelper::getRelativePath($this->getPath(), $path);
82
+    }
83
+
84
+    /**
85
+     * check if a node is a (grand-)child of the folder
86
+     *
87
+     * @param \OC\Files\Node\Node $node
88
+     * @return bool
89
+     */
90
+    public function isSubNode($node) {
91
+        return strpos($node->getPath(), $this->path . '/') === 0;
92
+    }
93
+
94
+    /**
95
+     * get the content of this directory
96
+     *
97
+     * @return Node[]
98
+     * @throws \OCP\Files\NotFoundException
99
+     */
100
+    public function getDirectoryListing() {
101
+        $folderContent = $this->view->getDirectoryContent($this->path, '', $this->getFileInfo());
102
+
103
+        return array_map(function (FileInfo $info) {
104
+            if ($info->getMimetype() === FileInfo::MIMETYPE_FOLDER) {
105
+                return new Folder($this->root, $this->view, $info->getPath(), $info, $this);
106
+            } else {
107
+                return new File($this->root, $this->view, $info->getPath(), $info, $this);
108
+            }
109
+        }, $folderContent);
110
+    }
111
+
112
+    /**
113
+     * @param string $path
114
+     * @param FileInfo $info
115
+     * @return File|Folder
116
+     */
117
+    protected function createNode($path, FileInfo $info = null) {
118
+        if (is_null($info)) {
119
+            $isDir = $this->view->is_dir($path);
120
+        } else {
121
+            $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
122
+        }
123
+        $parent = dirname($path) === $this->getPath() ? $this : null;
124
+        if ($isDir) {
125
+            return new Folder($this->root, $this->view, $path, $info, $parent);
126
+        } else {
127
+            return new File($this->root, $this->view, $path, $info, $parent);
128
+        }
129
+    }
130
+
131
+    /**
132
+     * Get the node at $path
133
+     *
134
+     * @param string $path
135
+     * @return \OC\Files\Node\Node
136
+     * @throws \OCP\Files\NotFoundException
137
+     */
138
+    public function get($path) {
139
+        return $this->root->get($this->getFullPath($path));
140
+    }
141
+
142
+    /**
143
+     * @param string $path
144
+     * @return bool
145
+     */
146
+    public function nodeExists($path) {
147
+        try {
148
+            $this->get($path);
149
+            return true;
150
+        } catch (NotFoundException $e) {
151
+            return false;
152
+        }
153
+    }
154
+
155
+    /**
156
+     * @param string $path
157
+     * @return \OC\Files\Node\Folder
158
+     * @throws \OCP\Files\NotPermittedException
159
+     */
160
+    public function newFolder($path) {
161
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
162
+            $fullPath = $this->getFullPath($path);
163
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
164
+            $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
165
+            if (!$this->view->mkdir($fullPath)) {
166
+                throw new NotPermittedException('Could not create folder');
167
+            }
168
+            $parent = dirname($fullPath) === $this->getPath() ? $this : null;
169
+            $node = new Folder($this->root, $this->view, $fullPath, null, $parent);
170
+            $this->sendHooks(['postWrite', 'postCreate'], [$node]);
171
+            return $node;
172
+        } else {
173
+            throw new NotPermittedException('No create permission for folder');
174
+        }
175
+    }
176
+
177
+    /**
178
+     * @param string $path
179
+     * @param string | resource | null $content
180
+     * @return \OC\Files\Node\File
181
+     * @throws \OCP\Files\NotPermittedException
182
+     */
183
+    public function newFile($path, $content = null) {
184
+        if (empty($path)) {
185
+            throw new NotPermittedException('Could not create as provided path is empty');
186
+        }
187
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
188
+            $fullPath = $this->getFullPath($path);
189
+            $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
190
+            $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
191
+            if ($content !== null) {
192
+                $result = $this->view->file_put_contents($fullPath, $content);
193
+            } else {
194
+                $result = $this->view->touch($fullPath);
195
+            }
196
+            if ($result === false) {
197
+                throw new NotPermittedException('Could not create path');
198
+            }
199
+            $node = new File($this->root, $this->view, $fullPath, null, $this);
200
+            $this->sendHooks(['postWrite', 'postCreate'], [$node]);
201
+            return $node;
202
+        }
203
+        throw new NotPermittedException('No create permission for path');
204
+    }
205
+
206
+    private function queryFromOperator(ISearchOperator $operator, string $uid = null): ISearchQuery {
207
+        if ($uid === null) {
208
+            $user = null;
209
+        } else {
210
+            /** @var IUserManager $userManager */
211
+            $userManager = \OC::$server->query(IUserManager::class);
212
+            $user = $userManager->get($uid);
213
+        }
214
+        return new SearchQuery($operator, 0, 0, [], $user);
215
+    }
216
+
217
+    /**
218
+     * search for files with the name matching $query
219
+     *
220
+     * @param string|ISearchQuery $query
221
+     * @return \OC\Files\Node\Node[]
222
+     */
223
+    public function search($query) {
224
+        if (is_string($query)) {
225
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
226
+        }
227
+
228
+        // search is handled by a single query covering all caches that this folder contains
229
+        // this is done by collect
230
+
231
+        $limitToHome = $query->limitToHome();
232
+        if ($limitToHome && count(explode('/', $this->path)) !== 3) {
233
+            throw new \InvalidArgumentException('searching by owner is only allows on the users home folder');
234
+        }
235
+
236
+        $rootLength = strlen($this->path);
237
+        $mount = $this->root->getMount($this->path);
238
+        $storage = $mount->getStorage();
239
+        $internalPath = $mount->getInternalPath($this->path);
240
+
241
+        // collect all caches for this folder, indexed by their mountpoint relative to this folder
242
+        // and save the mount which is needed later to construct the FileInfo objects
243
+
244
+        if ($internalPath !== '') {
245
+            // a temporary CacheJail is used to handle filtering down the results to within this folder
246
+            $caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
247
+        } else {
248
+            $caches = ['' => $storage->getCache('')];
249
+        }
250
+        $mountByMountPoint = ['' => $mount];
251
+
252
+        if (!$limitToHome) {
253
+            $mounts = $this->root->getMountsIn($this->path);
254
+            foreach ($mounts as $mount) {
255
+                $storage = $mount->getStorage();
256
+                if ($storage) {
257
+                    $relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
258
+                    $caches[$relativeMountPoint] = $storage->getCache('');
259
+                    $mountByMountPoint[$relativeMountPoint] = $mount;
260
+                }
261
+            }
262
+        }
263
+
264
+        /** @var QuerySearchHelper $searchHelper */
265
+        $searchHelper = \OC::$server->get(QuerySearchHelper::class);
266
+        $resultsPerCache = $searchHelper->searchInCaches($query, $caches);
267
+
268
+        // loop through all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
269
+        $files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
270
+            $mount = $mountByMountPoint[$relativeMountPoint];
271
+            return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
272
+                return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
273
+            }, $results);
274
+        }, array_values($resultsPerCache), array_keys($resultsPerCache)));
275
+
276
+        // don't include this folder in the results
277
+        $files = array_filter($files, function (FileInfo $file) {
278
+            return $file->getPath() !== $this->getPath();
279
+        });
280
+
281
+        // since results were returned per-cache, they are no longer fully sorted
282
+        $order = $query->getOrder();
283
+        if ($order) {
284
+            usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
285
+                foreach ($order as $orderField) {
286
+                    $cmp = $orderField->sortFileInfo($a, $b);
287
+                    if ($cmp !== 0) {
288
+                        return $cmp;
289
+                    }
290
+                }
291
+                return 0;
292
+            });
293
+        }
294
+
295
+        return array_map(function (FileInfo $file) {
296
+            return $this->createNode($file->getPath(), $file);
297
+        }, $files);
298
+    }
299
+
300
+    private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
301
+        $cacheEntry['internalPath'] = $cacheEntry['path'];
302
+        $cacheEntry['path'] = rtrim($appendRoot . $cacheEntry->getPath(), '/');
303
+        $subPath = $cacheEntry['path'] !== '' ? '/' . $cacheEntry['path'] : '';
304
+        return new \OC\Files\FileInfo($this->path . $subPath, $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
305
+    }
306
+
307
+    /**
308
+     * search for files by mimetype
309
+     *
310
+     * @param string $mimetype
311
+     * @return Node[]
312
+     */
313
+    public function searchByMime($mimetype) {
314
+        if (strpos($mimetype, '/') === false) {
315
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
316
+        } else {
317
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
318
+        }
319
+        return $this->search($query);
320
+    }
321
+
322
+    /**
323
+     * search for files by tag
324
+     *
325
+     * @param string|int $tag name or tag id
326
+     * @param string $userId owner of the tags
327
+     * @return Node[]
328
+     */
329
+    public function searchByTag($tag, $userId) {
330
+        $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', $tag), $userId);
331
+        return $this->search($query);
332
+    }
333
+
334
+    /**
335
+     * @param int $id
336
+     * @return \OC\Files\Node\Node[]
337
+     */
338
+    public function getById($id) {
339
+        return $this->root->getByIdInPath((int)$id, $this->getPath());
340
+    }
341
+
342
+    protected function getAppDataDirectoryName(): string {
343
+        $instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
344
+        return 'appdata_' . $instanceId;
345
+    }
346
+
347
+    /**
348
+     * In case the path we are currently in is inside the appdata_* folder,
349
+     * the original getById method does not work, because it can only look inside
350
+     * the user's mount points. But the user has no mount point for the root storage.
351
+     *
352
+     * So in that case we directly check the mount of the root if it contains
353
+     * the id. If it does we check if the path is inside the path we are working
354
+     * in.
355
+     *
356
+     * @param int $id
357
+     * @return array
358
+     */
359
+    protected function getByIdInRootMount(int $id): array {
360
+        $mount = $this->root->getMount('');
361
+        $cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
362
+        if (!$cacheEntry) {
363
+            return [];
364
+        }
365
+
366
+        $absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
367
+        $currentPath = rtrim($this->path, '/') . '/';
368
+
369
+        if (strpos($absolutePath, $currentPath) !== 0) {
370
+            return [];
371
+        }
372
+
373
+        return [$this->root->createNode(
374
+            $absolutePath, new \OC\Files\FileInfo(
375
+                $absolutePath,
376
+                $mount->getStorage(),
377
+                $cacheEntry->getPath(),
378
+                $cacheEntry,
379
+                $mount
380
+            ))];
381
+    }
382
+
383
+    public function getFreeSpace() {
384
+        return $this->view->free_space($this->path);
385
+    }
386
+
387
+    public function delete() {
388
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
389
+            $this->sendHooks(['preDelete']);
390
+            $fileInfo = $this->getFileInfo();
391
+            $this->view->rmdir($this->path);
392
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
393
+            $this->sendHooks(['postDelete'], [$nonExisting]);
394
+        } else {
395
+            throw new NotPermittedException('No delete permission for path');
396
+        }
397
+    }
398
+
399
+    /**
400
+     * Add a suffix to the name in case the file exists
401
+     *
402
+     * @param string $name
403
+     * @return string
404
+     * @throws NotPermittedException
405
+     */
406
+    public function getNonExistingName($name) {
407
+        $uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
408
+        return trim($this->getRelativePath($uniqueName), '/');
409
+    }
410
+
411
+    /**
412
+     * @param int $limit
413
+     * @param int $offset
414
+     * @return \OCP\Files\Node[]
415
+     */
416
+    public function getRecent($limit, $offset = 0) {
417
+        $filterOutNonEmptyFolder = new SearchBinaryOperator(
418
+            // filter out non empty folders
419
+            ISearchBinaryOperator::OPERATOR_OR,
420
+            [
421
+                new SearchBinaryOperator(
422
+                    ISearchBinaryOperator::OPERATOR_NOT,
423
+                    [
424
+                        new SearchComparison(
425
+                            ISearchComparison::COMPARE_EQUAL,
426
+                            'mimetype',
427
+                            FileInfo::MIMETYPE_FOLDER
428
+                        ),
429
+                    ]
430
+                ),
431
+                new SearchComparison(
432
+                    ISearchComparison::COMPARE_EQUAL,
433
+                    'size',
434
+                    0
435
+                ),
436
+            ]
437
+        );
438
+
439
+        $filterNonRecentFiles = new SearchComparison(
440
+            ISearchComparison::COMPARE_GREATER_THAN,
441
+            'mtime',
442
+            strtotime("-2 week")
443
+        );
444
+        if ($offset === 0 && $limit <= 100) {
445
+            $query = new SearchQuery(
446
+                new SearchBinaryOperator(
447
+                    ISearchBinaryOperator::OPERATOR_AND,
448
+                    [
449
+                        $filterOutNonEmptyFolder,
450
+                        $filterNonRecentFiles,
451
+                    ],
452
+                ),
453
+                $limit,
454
+                $offset,
455
+                [
456
+                    new SearchOrder(
457
+                        ISearchOrder::DIRECTION_DESCENDING,
458
+                        'mtime'
459
+                    ),
460
+                ]
461
+            );
462
+        } else {
463
+            $query = new SearchQuery(
464
+                $filterOutNonEmptyFolder,
465
+                $limit,
466
+                $offset,
467
+                [
468
+                    new SearchOrder(
469
+                        ISearchOrder::DIRECTION_DESCENDING,
470
+                        'mtime'
471
+                    ),
472
+                ]
473
+            );
474
+        }
475
+
476
+        return $this->search($query);
477
+    }
478 478
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
 		if (!$this->isValidPath($path)) {
71 71
 			throw new NotPermittedException('Invalid path');
72 72
 		}
73
-		return $this->path . $path;
73
+		return $this->path.$path;
74 74
 	}
75 75
 
76 76
 	/**
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
 	 * @return bool
89 89
 	 */
90 90
 	public function isSubNode($node) {
91
-		return strpos($node->getPath(), $this->path . '/') === 0;
91
+		return strpos($node->getPath(), $this->path.'/') === 0;
92 92
 	}
93 93
 
94 94
 	/**
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
 	public function getDirectoryListing() {
101 101
 		$folderContent = $this->view->getDirectoryContent($this->path, '', $this->getFileInfo());
102 102
 
103
-		return array_map(function (FileInfo $info) {
103
+		return array_map(function(FileInfo $info) {
104 104
 			if ($info->getMimetype() === FileInfo::MIMETYPE_FOLDER) {
105 105
 				return new Folder($this->root, $this->view, $info->getPath(), $info, $this);
106 106
 			} else {
@@ -222,7 +222,7 @@  discard block
 block discarded – undo
222 222
 	 */
223 223
 	public function search($query) {
224 224
 		if (is_string($query)) {
225
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
225
+			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%'.$query.'%'));
226 226
 		}
227 227
 
228 228
 		// search is handled by a single query covering all caches that this folder contains
@@ -266,22 +266,22 @@  discard block
 block discarded – undo
266 266
 		$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
267 267
 
268 268
 		// loop through all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
269
-		$files = array_merge(...array_map(function (array $results, $relativeMountPoint) use ($mountByMountPoint) {
269
+		$files = array_merge(...array_map(function(array $results, $relativeMountPoint) use ($mountByMountPoint) {
270 270
 			$mount = $mountByMountPoint[$relativeMountPoint];
271
-			return array_map(function (ICacheEntry $result) use ($relativeMountPoint, $mount) {
271
+			return array_map(function(ICacheEntry $result) use ($relativeMountPoint, $mount) {
272 272
 				return $this->cacheEntryToFileInfo($mount, $relativeMountPoint, $result);
273 273
 			}, $results);
274 274
 		}, array_values($resultsPerCache), array_keys($resultsPerCache)));
275 275
 
276 276
 		// don't include this folder in the results
277
-		$files = array_filter($files, function (FileInfo $file) {
277
+		$files = array_filter($files, function(FileInfo $file) {
278 278
 			return $file->getPath() !== $this->getPath();
279 279
 		});
280 280
 
281 281
 		// since results were returned per-cache, they are no longer fully sorted
282 282
 		$order = $query->getOrder();
283 283
 		if ($order) {
284
-			usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
284
+			usort($files, function(FileInfo $a, FileInfo $b) use ($order) {
285 285
 				foreach ($order as $orderField) {
286 286
 					$cmp = $orderField->sortFileInfo($a, $b);
287 287
 					if ($cmp !== 0) {
@@ -292,16 +292,16 @@  discard block
 block discarded – undo
292 292
 			});
293 293
 		}
294 294
 
295
-		return array_map(function (FileInfo $file) {
295
+		return array_map(function(FileInfo $file) {
296 296
 			return $this->createNode($file->getPath(), $file);
297 297
 		}, $files);
298 298
 	}
299 299
 
300 300
 	private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, ICacheEntry $cacheEntry): FileInfo {
301 301
 		$cacheEntry['internalPath'] = $cacheEntry['path'];
302
-		$cacheEntry['path'] = rtrim($appendRoot . $cacheEntry->getPath(), '/');
303
-		$subPath = $cacheEntry['path'] !== '' ? '/' . $cacheEntry['path'] : '';
304
-		return new \OC\Files\FileInfo($this->path . $subPath, $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
302
+		$cacheEntry['path'] = rtrim($appendRoot.$cacheEntry->getPath(), '/');
303
+		$subPath = $cacheEntry['path'] !== '' ? '/'.$cacheEntry['path'] : '';
304
+		return new \OC\Files\FileInfo($this->path.$subPath, $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
305 305
 	}
306 306
 
307 307
 	/**
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
 	 */
313 313
 	public function searchByMime($mimetype) {
314 314
 		if (strpos($mimetype, '/') === false) {
315
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
315
+			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype.'/%'));
316 316
 		} else {
317 317
 			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
318 318
 		}
@@ -336,12 +336,12 @@  discard block
 block discarded – undo
336 336
 	 * @return \OC\Files\Node\Node[]
337 337
 	 */
338 338
 	public function getById($id) {
339
-		return $this->root->getByIdInPath((int)$id, $this->getPath());
339
+		return $this->root->getByIdInPath((int) $id, $this->getPath());
340 340
 	}
341 341
 
342 342
 	protected function getAppDataDirectoryName(): string {
343 343
 		$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
344
-		return 'appdata_' . $instanceId;
344
+		return 'appdata_'.$instanceId;
345 345
 	}
346 346
 
347 347
 	/**
@@ -363,8 +363,8 @@  discard block
 block discarded – undo
363 363
 			return [];
364 364
 		}
365 365
 
366
-		$absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
367
-		$currentPath = rtrim($this->path, '/') . '/';
366
+		$absolutePath = '/'.ltrim($cacheEntry->getPath(), '/');
367
+		$currentPath = rtrim($this->path, '/').'/';
368 368
 
369 369
 		if (strpos($absolutePath, $currentPath) !== 0) {
370 370
 			return [];
Please login to merge, or discard this patch.