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
44 changes: 31 additions & 13 deletions apps/dav/lib/Connector/Sabre/TagsPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public function initialize(\Sabre\DAV\Server $server) {
$this->server = $server;
$this->server->on('propFind', [$this, 'handleGetProperties']);
$this->server->on('propPatch', [$this, 'handleUpdateProperties']);
$this->server->on('preloadProperties', [$this, 'handlePreloadProperties']);
}

/**
Expand Down Expand Up @@ -149,6 +150,24 @@ private function getTags($fileId) {
return null;
}

/**
* Prefetches tags for a list of file IDs and caches the results
*
* @param array $fileIds List of file IDs to prefetch tags for
* @return void
*/
private function prefetchTagsForFileIds(array $fileIds) {
$tags = $this->getTagger()->getTagsForObjects($fileIds);
if ($tags === false) {
// the tags API returns false on error...
$tags = [];
}

foreach ($fileIds as $fileId) {
$this->cachedTags[$fileId] = $tags[$fileId] ?? [];
}
}

/**
* Updates the tags of the given file id
*
Expand Down Expand Up @@ -199,22 +218,11 @@ public function handleGetProperties(
)) {
// note: pre-fetching only supported for depth <= 1
$folderContent = $node->getChildren();
$fileIds[] = (int)$node->getId();
$fileIds = [(int)$node->getId()];
foreach ($folderContent as $info) {
$fileIds[] = (int)$info->getId();
}
$tags = $this->getTagger()->getTagsForObjects($fileIds);
if ($tags === false) {
// the tags API returns false on error...
$tags = [];
}

$this->cachedTags = $this->cachedTags + $tags;
$emptyFileIds = array_diff($fileIds, array_keys($tags));
// also cache the ones that were not found
foreach ($emptyFileIds as $fileId) {
$this->cachedTags[$fileId] = [];
}
$this->prefetchTagsForFileIds($fileIds);
}

$isFav = null;
Expand Down Expand Up @@ -270,4 +278,14 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
return 200;
});
}

public function handlePreloadProperties(array $nodes, array $requestProperties): void {
if (
!in_array(self::FAVORITE_PROPERTYNAME, $requestProperties, true) &&
!in_array(self::TAGS_PROPERTYNAME, $requestProperties, true)
) {
return;
}
$this->prefetchTagsForFileIds(array_map(fn ($node) => $node->getId(), $nodes));
}
}
3 changes: 3 additions & 0 deletions apps/dav/lib/Files/FileSearchBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Connector\Sabre\TagsPlugin;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Folder;
Expand Down Expand Up @@ -44,6 +45,7 @@ class FileSearchBackend implements ISearchBackend {
public const OPERATOR_LIMIT = 100;

public function __construct(
private Server $server,
private CachingTree $tree,
private IUser $user,
private IRootFolder $rootFolder,
Expand Down Expand Up @@ -133,6 +135,7 @@ private function getPropertyDefinitionsForMetadata(): array {
* @param string[] $requestProperties
*/
public function preloadPropertyFor(array $nodes, array $requestProperties): void {
$this->server->emit('preloadProperties', [$nodes, $requestProperties]);
}

private function getFolderForPath(?string $path = null): Folder {
Expand Down
1 change: 1 addition & 0 deletions apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ public function __construct(
\OCP\Server::get(IAppManager::class)
));
$lazySearchBackend->setBackend(new FileSearchBackend(
$this->server,
$this->server->tree,
$user,
\OCP\Server::get(IRootFolder::class),
Expand Down
18 changes: 17 additions & 1 deletion apps/dav/tests/unit/Files/FileSearchBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\ObjectTree;
use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Files\FileSearchBackend;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
Expand All @@ -36,6 +37,7 @@

class FileSearchBackendTest extends TestCase {
private ObjectTree&MockObject $tree;
private Server&MockObject $server;
private IUser&MockObject $user;
private IRootFolder&MockObject $rootFolder;
private IManager&MockObject $shareManager;
Expand All @@ -53,6 +55,7 @@ protected function setUp(): void {
->willReturn('test');

$this->tree = $this->createMock(ObjectTree::class);
$this->server = $this->createMock(Server::class);
$this->view = $this->createMock(View::class);
$this->rootFolder = $this->createMock(IRootFolder::class);
$this->shareManager = $this->createMock(IManager::class);
Expand All @@ -78,7 +81,7 @@ protected function setUp(): void {

$filesMetadataManager = $this->createMock(IFilesMetadataManager::class);

$this->search = new FileSearchBackend($this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
$this->search = new FileSearchBackend($this->server, $this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
}

public function testSearchFilename(): void {
Expand Down Expand Up @@ -402,4 +405,17 @@ public function testSearchOperatorLimit(): void {
$this->expectException(\InvalidArgumentException::class);
$this->search->search($query);
}

public function testPreloadPropertyFor(): void {
$node1 = $this->createMock(File::class);
$node2 = $this->createMock(Directory::class);
$nodes = [$node1, $node2];
$requestProperties = ['{DAV:}getcontenttype', '{DAV:}getlastmodified'];

$this->server->expects($this->once())
->method('emit')
->with('preloadProperties', [$nodes, $requestProperties]);

$this->search->preloadPropertyFor($nodes, $requestProperties);
}
}
Loading