WebDAV collection preload events
Overview
During a WebDAV PROPFIND on a SabreDAV collection with Depth > 0
,
Nextcloud emits a preload event so DAV plugins can fetch data for the
collection’s children in one go. The goal is to avoid N+1 database queries by
preloading what your property handlers need before per-node property handling
starts. In practice, this means your plugin can fill a cache up front, then
read from it in the usual propFind
handlers for a faster and more
efficient response.
When the event is emitted
The event is emitted during PROPFIND requests, before the propFind
event,
for nodes implementing Sabre\DAV\ICollection
with Depth > 0
.
The event may be emitted multiple times for a given request path; plugins should check their caches to avoid duplicate work.
Subscribing to the event in a plugin
Register a listener in your implementation of Sabre’s ServerPlugin::initialize()
method:
use Sabre\DAV\ICollection;
use Sabre\DAV\PropFind;
use Sabre\DAV\ServerPlugin;
class MyDavPlugin extends ServerPlugin {
public function initialize(\Sabre\DAV\Server $server): void {
// Called before per-node property handlers
$server->on('preloadCollection', $this->preloadCollection(...));
// Your usual property handlers
$server->on('propFind', $this->handleGetProperties(...));
}
private function preloadCollection(PropFind $propFind, ICollection $collection): void {
// Only preload when your properties were actually requested
$requested = [
'{http://appdomain.example/ns}your-prop',
'{http://appdomain.example/ns}another-prop',
];
$anyRequested = array_reduce(
$requested,
fn($result, $property) => $result || $propFind->getStatus($property) !== null,
false
);
if (!$anyRequested) {
return;
}
// Fetch data for the collection and its children in bulk
// and cache results for use in your propFind handler
$this->cache = $this->bulkLoadDataForCollection($collection); // implement your own caching
}
private function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node): void {
// Read and return values from $this->cache to avoid per-node queries
// Handle per-node property loading here to support Depth = 0
// and cases where the 'preloadCollection' event is not emitted.
}
}
Built-in examples
Tags:
OCA\DAV\Connector\Sabre\TagsPlugin
preloads tags and favorite info for a folder and its children.Shares:
OCA\DAV\Connector\Sabre\SharesPlugin
preloads share types and sharees for items within a folder.Comments:
OCA\DAV\Connector\Sabre\CommentPropertiesPlugin
preloads unread comment counts for items within a folder.
Best practices
Check requested properties: Use
$propFind->getStatus('{ns}property')
to confirm that your properties were actually requested before querying.Cache results: The event can fire multiple times; cache by file ID or path to avoid redundant work during the same request.
Scope your preload: Only fetch data for the current collection and (at most) its direct children; avoid fetching across the whole tree.