Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions lib/private/Files/Cache/QuerySearchHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@
namespace OC\Files\Cache;

use OC\Files\Cache\Wrapper\CacheJail;
use OC\Files\Node\Root;
use OC\Files\Search\QueryOptimizer\QueryOptimizer;
use OC\Files\Search\SearchBinaryOperator;
use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Folder;
use OCP\Files\IMimeTypeLoader;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchQuery;
Expand Down Expand Up @@ -197,24 +196,29 @@ public function searchInCaches(ISearchQuery $searchQuery, array $caches): array
}

/**
* @return array{array<string, ICache>, array<string, IMountPoint>}
* @return array{0?: array<array-key, ICache>, 1?: array<array-key, IMountPoint>}
*/
public function getCachesAndMountPointsForSearch(Root $root, string $path, bool $limitToHome = false): array {
public function getCachesAndMountPointsForSearch(IRootFolder $root, string $path, bool $limitToHome = false): array {
$rootLength = strlen($path);
$mount = $root->getMount($path);
$storage = $mount->getStorage();
if ($storage === null) {
return [];
}
$internalPath = $mount->getInternalPath($path);

if ($internalPath !== '') {
// a temporary CacheJail is used to handle filtering down the results to within this folder
/** @var ICache[] $caches */
$caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
} else {
/** @var ICache[] $caches */
$caches = ['' => $storage->getCache('')];
}
/** @var IMountPoint[] $mountByMountPoint */
$mountByMountPoint = ['' => $mount];

if (!$limitToHome) {
/** @var IMountPoint[] $mounts */
$mounts = $root->getMountsIn($path);
foreach ($mounts as $mount) {
$storage = $mount->getStorage();
Expand Down
3 changes: 0 additions & 3 deletions lib/private/Files/FileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,6 @@ public function getPath() {
return $this->path;
}

/**
* @return \OCP\Files\Storage
*/
public function getStorage() {
return $this->storage;
}
Expand Down
25 changes: 15 additions & 10 deletions lib/private/Files/Node/Folder.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\FileInfo;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Node as INode;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\Search\ISearchBinaryOperator;
Expand Down Expand Up @@ -108,12 +109,7 @@ public function getDirectoryListing() {
}, $folderContent);
}

/**
* @param string $path
* @param FileInfo $info
* @return File|Folder
*/
protected function createNode($path, FileInfo $info = null) {
protected function createNode(string $path, ?FileInfo $info = null): INode {
if (is_null($info)) {
$isDir = $this->view->is_dir($path);
} else {
Expand Down Expand Up @@ -234,6 +230,8 @@ public function search($query) {

/** @var QuerySearchHelper $searchHelper */
$searchHelper = \OC::$server->get(QuerySearchHelper::class);
/** @var \OCP\Files\Cache\ICache[] $caches */
/** @var \OCP\Files\Mount\IMountPoint[] $mountByMountPoint */
[$caches, $mountByMountPoint] = $searchHelper->getCachesAndMountPointsForSearch($this->root, $this->path, $limitToHome);
$resultsPerCache = $searchHelper->searchInCaches($query, $caches);

Expand Down Expand Up @@ -328,9 +326,16 @@ protected function getAppDataDirectoryName(): string {
* @param int $id
* @return array
*/
protected function getByIdInRootMount(int $id): array {
protected function getByIdInRootMount(int $id): array {
if (!method_exists($this->root, 'createNode')) {
// Always expected to be false. Being a method of Folder, this is
// always implemented. For it is an internal method and should not
// be exposed and made public, it is not part of an interface.
return [];
}
$mount = $this->root->getMount('');
$cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
$storage = $mount->getStorage();
$cacheEntry = $storage ? $storage->getCache($this->path)->get($id) : null;
if (!$cacheEntry) {
return [];
}
Expand All @@ -345,7 +350,7 @@ protected function getByIdInRootMount(int $id): array {
return [$this->root->createNode(
$absolutePath, new \OC\Files\FileInfo(
$absolutePath,
$mount->getStorage(),
$storage,
$cacheEntry->getPath(),
$cacheEntry,
$mount
Expand Down Expand Up @@ -383,7 +388,7 @@ public function getNonExistingName($name) {
/**
* @param int $limit
* @param int $offset
* @return \OCP\Files\Node[]
* @return INode[]
*/
public function getRecent($limit, $offset = 0) {
$filterOutNonEmptyFolder = new SearchBinaryOperator(
Expand Down
7 changes: 4 additions & 3 deletions lib/private/Files/Node/LazyFolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

use OC\Files\Utils\PathHelper;
use OCP\Constants;
use OCP\Files\Mount\IMountPoint;

/**
* Class LazyFolder
Expand Down Expand Up @@ -110,14 +111,14 @@ public function mount($storage, $mountPoint, $arguments = []) {
/**
* @inheritDoc
*/
public function getMount($mountPoint) {
public function getMount(string $mountPoint): IMountPoint {
return $this->__call(__FUNCTION__, func_get_args());
}

/**
* @inheritDoc
* @return IMountPoint[]
*/
public function getMountsIn($mountPoint) {
public function getMountsIn(string $mountPoint): array {
return $this->__call(__FUNCTION__, func_get_args());
}

Expand Down
22 changes: 12 additions & 10 deletions lib/private/Files/Node/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,22 @@
use OC\Files\Utils\PathHelper;
use OCP\Files\FileInfo;
use OCP\Files\InvalidPathException;
use OCP\Files\IRootFolder;
use OCP\Files\Node as INode;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
use Symfony\Component\EventDispatcher\GenericEvent;

// FIXME: this class really should be abstract
class Node implements \OCP\Files\Node {
class Node implements INode {
/**
* @var \OC\Files\View $view
*/
protected $view;

/**
* @var \OC\Files\Node\Root $root
*/
protected $root;
protected IRootFolder $root;

/**
* @var string $path Absolute path to the node (e.g. /admin/files/folder/file)
Expand All @@ -73,7 +72,7 @@ class Node implements \OCP\Files\Node {
* @param string $path
* @param FileInfo $fileInfo
*/
public function __construct($root, $view, $path, $fileInfo = null, ?Node $parent = null) {
public function __construct(IRootFolder $root, $view, $path, $fileInfo = null, ?Node $parent = null) {
if (Filesystem::normalizePath($view->getRoot()) !== '/') {
throw new PreConditionNotMetException('The view passed to the node should not have any fake root set');
}
Expand Down Expand Up @@ -124,7 +123,9 @@ protected function sendHooks($hooks, array $args = null) {
$args = !empty($args) ? $args : [$this];
$dispatcher = \OC::$server->getEventDispatcher();
foreach ($hooks as $hook) {
$this->root->emit('\OC\Files', $hook, $args);
if (method_exists($this->root, 'emit')) {
$this->root->emit('\OC\Files', $hook, $args);
}
$dispatcher->dispatch('\OCP\Files::' . $hook, new GenericEvent($args));
}
}
Expand Down Expand Up @@ -285,7 +286,8 @@ public function isCreatable() {
}

/**
* @return Node
* @return INode|IRootFolder

Check failure

Code scanning / Psalm

LessSpecificImplementedReturnType

The inherited return type 'OCP\Files\Folder' for OCP\Files\Node::getParent is more specific than the implemented return type for OC\Files\Node\Node::getparent 'OCP\Files\IRootFolder|OCP\Files\Node'
* @throws NotFoundException
*/
public function getParent() {
if ($this->parent === null) {
Expand Down Expand Up @@ -396,7 +398,7 @@ public function unlock($type) {

/**
* @param string $targetPath
* @return \OC\Files\Node\Node
* @return INode
* @throws InvalidPathException
* @throws NotFoundException
* @throws NotPermittedException if copy not allowed or failed
Expand All @@ -422,7 +424,7 @@ public function copy($targetPath) {

/**
* @param string $targetPath
* @return \OC\Files\Node\Node
* @return INode
* @throws InvalidPathException
* @throws NotFoundException
* @throws NotPermittedException if move not allowed or failed
Expand Down
11 changes: 4 additions & 7 deletions lib/private/Files/Node/Root.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Node as INode;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IUser;
Expand Down Expand Up @@ -153,19 +154,15 @@ public function mount($storage, $mountPoint, $arguments = []) {
$this->mountManager->addMount($mount);
}

/**
* @param string $mountPoint
* @return \OC\Files\Mount\MountPoint
*/
public function getMount($mountPoint) {
public function getMount(string $mountPoint): IMountPoint {
return $this->mountManager->find($mountPoint);
}

/**
* @param string $mountPoint
* @return \OC\Files\Mount\MountPoint[]
*/
public function getMountsIn($mountPoint) {
public function getMountsIn(string $mountPoint): array {
return $this->mountManager->findIn($mountPoint);
}

Expand Down Expand Up @@ -339,7 +336,7 @@ public function isShareable() {
}

/**
* @return Node
* @return INode|IRootFolder

Check failure

Code scanning / Psalm

LessSpecificImplementedReturnType

The inherited return type 'OCP\Files\Folder' for OCP\Files\Node::getParent is more specific than the implemented return type for OC\Files\Node\Root::getparent 'OCP\Files\IRootFolder|OCP\Files\Node'
* @throws \OCP\Files\NotFoundException
*/
public function getParent() {
Expand Down
1 change: 1 addition & 0 deletions lib/private/SystemTag/SystemTagsInFilesDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public function detectAssignedSystemTagsIn(
}

$query = new SearchQuery($operator, $limit, $offset, []);
/** @var \OCP\Files\Cache\ICache[] $caches */
[$caches, ] = $this->searchHelper->getCachesAndMountPointsForSearch(
$this->getRootFolder($folder),
$folder->getPath(),
Expand Down
13 changes: 13 additions & 0 deletions lib/public/Files/IRootFolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

use OC\Hooks\Emitter;
use OC\User\NoUserException;
use OCP\Files\Mount\IMountPoint;

/**
* Interface IRootFolder
Expand Down Expand Up @@ -56,4 +57,16 @@ public function getUserFolder($userId);
* @since 24.0.0
*/
public function getByIdInPath(int $id, string $path);

/**
* @return IMountPoint[]
*
* @since 25.0.9
*/
public function getMountsIn(string $mountPoint): array;

/**
* @since 25.0.9
*/
public function getMount(string $mountPoint): IMountPoint;
}
8 changes: 5 additions & 3 deletions tests/lib/Files/Node/FolderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use OC\Files\Storage\Temporary;
use OC\Files\Storage\Wrapper\Jail;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
use OCP\Files\Search\ISearchComparison;
Expand Down Expand Up @@ -462,12 +463,13 @@ public function testSearchSubStorages() {
}

public function testIsSubNode() {
$file = new Node(null, $this->view, '/foo/bar');
$folder = new Folder(null, $this->view, '/foo');
$rootFolderMock = $this->createMock(IRootFolder::class);
$file = new Node($rootFolderMock, $this->view, '/foo/bar');
$folder = new Folder($rootFolderMock, $this->view, '/foo');
$this->assertTrue($folder->isSubNode($file));
$this->assertFalse($folder->isSubNode($folder));

$file = new Node(null, $this->view, '/foobar');
$file = new Node($rootFolderMock, $this->view, '/foobar');
$this->assertFalse($folder->isSubNode($file));
}

Expand Down