|
22 | 22 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
23 | 23 | * |
24 | 24 | */ |
| 25 | + |
25 | 26 | namespace OCA\DAV\DAV; |
26 | 27 |
|
27 | 28 | use Exception; |
| 29 | +use OCA\DAV\Connector\Sabre\Directory; |
28 | 30 | use OCP\DB\QueryBuilder\IQueryBuilder; |
29 | 31 | use OCP\IDBConnection; |
30 | 32 | use OCP\IUser; |
@@ -134,7 +136,8 @@ class CustomPropertiesBackend implements BackendInterface { |
134 | 136 | public function __construct( |
135 | 137 | Tree $tree, |
136 | 138 | IDBConnection $connection, |
137 | | - IUser $user) { |
| 139 | + IUser $user |
| 140 | + ) { |
138 | 141 | $this->tree = $tree; |
139 | 142 | $this->connection = $connection; |
140 | 143 | $this->user = $user; |
@@ -180,6 +183,11 @@ public function propFind($path, PropFind $propFind) { |
180 | 183 | return; |
181 | 184 | } |
182 | 185 |
|
| 186 | + $node = $this->tree->getNodeForPath($path); |
| 187 | + if ($node instanceof Directory && $propFind->getDepth() !== 0) { |
| 188 | + $this->cacheDirectory($path, $node); |
| 189 | + } |
| 190 | + |
183 | 191 | // First fetch the published properties (set by another user), then get the ones set by |
184 | 192 | // the current user. If both are set then the latter as priority. |
185 | 193 | foreach ($this->getPublishedProperties($path, $requestedProps) as $propName => $propValue) { |
@@ -262,6 +270,38 @@ private function getPublishedProperties(string $path, array $requestedProperties |
262 | 270 | return $props; |
263 | 271 | } |
264 | 272 |
|
| 273 | + /** |
| 274 | + * prefetch all user properties in a directory |
| 275 | + */ |
| 276 | + private function cacheDirectory(string $path, Directory $node): void { |
| 277 | + $prefix = ltrim($path . '/', '/'); |
| 278 | + $query = $this->connection->getQueryBuilder(); |
| 279 | + $query->select('name', 'propertypath', 'propertyname', 'propertyvalue', 'valuetype') |
| 280 | + ->from('filecache', 'f') |
| 281 | + ->leftJoin('f', 'properties', 'p', $query->expr()->andX( |
| 282 | + $query->expr()->eq('propertypath', $query->func()->concat( |
| 283 | + $query->createNamedParameter($prefix), |
| 284 | + 'name' |
| 285 | + )), |
| 286 | + $query->expr()->eq('userid', $query->createNamedParameter($this->user->getUID())) |
| 287 | + )) |
| 288 | + ->where($query->expr()->eq('parent', $query->createNamedParameter($node->getInternalFileId(), IQueryBuilder::PARAM_INT))); |
| 289 | + $result = $query->executeQuery(); |
| 290 | + |
| 291 | + $propsByPath = []; |
| 292 | + |
| 293 | + while ($row = $result->fetch()) { |
| 294 | + $childPath = $prefix . $row['name']; |
| 295 | + if (!isset($propsByPath[$childPath])) { |
| 296 | + $propsByPath[$childPath] = []; |
| 297 | + } |
| 298 | + if (isset($row['propertyname'])) { |
| 299 | + $propsByPath[$childPath][$row['propertyname']] = $this->decodeValueFromDatabase($row['propertyvalue'], $row['valuetype']); |
| 300 | + } |
| 301 | + } |
| 302 | + $this->userCache = array_merge($this->userCache, $propsByPath); |
| 303 | + } |
| 304 | + |
265 | 305 | /** |
266 | 306 | * Returns a list of properties for the given path and current user |
267 | 307 | * |
@@ -321,7 +361,7 @@ private function updateProperties(string $path, array $properties): bool { |
321 | 361 | $dbParameters = [ |
322 | 362 | 'userid' => $this->user->getUID(), |
323 | 363 | 'propertyPath' => $this->formatPath($path), |
324 | | - 'propertyName' => $propertyName |
| 364 | + 'propertyName' => $propertyName, |
325 | 365 | ]; |
326 | 366 |
|
327 | 367 | // If it was null, we need to delete the property |
|
0 commit comments