Skip to content

Commit ec465bf

Browse files
authored
Merge pull request #33090 from nextcloud/fix/noid/proppatch-properties-transaction-rollback
DAV custom props: catch Exception and rollback transaction in case
2 parents ef607e3 + 794177e commit ec465bf

File tree

1 file changed

+76
-54
lines changed

1 file changed

+76
-54
lines changed

apps/dav/lib/DAV/CustomPropertiesBackend.php

Lines changed: 76 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
*/
2525
namespace OCA\DAV\DAV;
2626

27-
use OCA\DAV\Connector\Sabre\Node;
27+
use OCP\DB\Exception;
28+
use OCP\DB\QueryBuilder\IQueryBuilder;
2829
use OCP\IDBConnection;
2930
use OCP\IUser;
3031
use Sabre\DAV\PropertyStorage\Backend\BackendInterface;
@@ -308,66 +309,54 @@ private function getUserProperties(string $path, array $requestedProperties) {
308309
}
309310

310311
/**
311-
* Update properties
312-
*
313-
* @param string $path path for which to update properties
314-
* @param array $properties array of properties to update
315-
*
316-
* @return bool
312+
* @throws Exception
317313
*/
318-
private function updateProperties(string $path, array $properties) {
319-
$deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
320-
' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
321-
322-
$insertStatement = 'INSERT INTO `*PREFIX*properties`' .
323-
' (`userid`,`propertypath`,`propertyname`,`propertyvalue`, `valuetype`) VALUES(?,?,?,?,?)';
324-
325-
$updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?, `valuetype` = ?' .
326-
' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
327-
314+
private function updateProperties(string $path, array $properties): bool {
328315
// TODO: use "insert or update" strategy ?
329316
$existing = $this->getUserProperties($path, []);
330-
$this->connection->beginTransaction();
331-
foreach ($properties as $propertyName => $propertyValue) {
332-
// If it was null, we need to delete the property
333-
if (is_null($propertyValue)) {
334-
if (array_key_exists($propertyName, $existing)) {
335-
$this->connection->executeUpdate($deleteStatement,
336-
[
337-
$this->user->getUID(),
338-
$this->formatPath($path),
339-
$propertyName,
340-
]
341-
);
342-
}
343-
} else {
344-
[$value, $valueType] = $this->encodeValueForDatabase($propertyValue);
345-
if (!array_key_exists($propertyName, $existing)) {
346-
$this->connection->executeUpdate($insertStatement,
347-
[
348-
$this->user->getUID(),
349-
$this->formatPath($path),
350-
$propertyName,
351-
$value,
352-
$valueType
353-
]
354-
);
317+
try {
318+
$this->connection->beginTransaction();
319+
foreach ($properties as $propertyName => $propertyValue) {
320+
// common parameters for all queries
321+
$dbParameters = [
322+
'userid' => $this->user->getUID(),
323+
'propertyPath' => $this->formatPath($path),
324+
'propertyName' => $propertyName
325+
];
326+
327+
// If it was null, we need to delete the property
328+
if (is_null($propertyValue)) {
329+
if (array_key_exists($propertyName, $existing)) {
330+
$deleteQuery = $deleteQuery ?? $this->createDeleteQuery();
331+
$deleteQuery
332+
->setParameters($dbParameters)
333+
->executeStatement();
334+
}
355335
} else {
356-
$this->connection->executeUpdate($updateStatement,
357-
[
358-
$value,
359-
$valueType,
360-
$this->user->getUID(),
361-
$this->formatPath($path),
362-
$propertyName,
363-
]
364-
);
336+
[$value, $valueType] = $this->encodeValueForDatabase($propertyValue);
337+
$dbParameters['propertyValue'] = $value;
338+
$dbParameters['valueType'] = $valueType;
339+
340+
if (!array_key_exists($propertyName, $existing)) {
341+
$insertQuery = $insertQuery ?? $this->createInsertQuery();
342+
$insertQuery
343+
->setParameters($dbParameters)
344+
->executeStatement();
345+
} else {
346+
$updateQuery = $updateQuery ?? $this->createUpdateQuery();
347+
$updateQuery
348+
->setParameters($dbParameters)
349+
->executeStatement();
350+
}
365351
}
366352
}
367-
}
368353

369-
$this->connection->commit();
370-
unset($this->userCache[$path]);
354+
$this->connection->commit();
355+
unset($this->userCache[$path]);
356+
} catch (Exception $e) {
357+
$this->connection->rollBack();
358+
throw $e;
359+
}
371360

372361
return true;
373362
}
@@ -417,4 +406,37 @@ private function decodeValueFromDatabase(string $value, int $valueType) {
417406
return $value;
418407
}
419408
}
409+
410+
private function createDeleteQuery(): IQueryBuilder {
411+
$deleteQuery = $this->connection->getQueryBuilder();
412+
$deleteQuery->delete('properties')
413+
->where($deleteQuery->expr()->eq('userid', $deleteQuery->createParameter('userid')))
414+
->andWhere($deleteQuery->expr()->eq('propertypath', $deleteQuery->createParameter('propertyPath')))
415+
->andWhere($deleteQuery->expr()->eq('propertyname', $deleteQuery->createParameter('propertyName')));
416+
return $deleteQuery;
417+
}
418+
419+
private function createInsertQuery(): IQueryBuilder {
420+
$insertQuery = $this->connection->getQueryBuilder();
421+
$insertQuery->insert('properties')
422+
->values([
423+
'userid' => $insertQuery->createParameter('userid'),
424+
'propertypath' => $insertQuery->createParameter('propertyPath'),
425+
'propertyname' => $insertQuery->createParameter('propertyName'),
426+
'propertyvalue' => $insertQuery->createParameter('propertyValue'),
427+
'valuetype' => $insertQuery->createParameter('valueType'),
428+
]);
429+
return $insertQuery;
430+
}
431+
432+
private function createUpdateQuery(): IQueryBuilder {
433+
$updateQuery = $this->connection->getQueryBuilder();
434+
$updateQuery->update('properties')
435+
->set('propertyvalue', $updateQuery->createParameter('propertyValue'))
436+
->set('valuetype', $updateQuery->createParameter('valueType'))
437+
->where($updateQuery->expr()->eq('userid', $updateQuery->createParameter('userid')))
438+
->andWhere($updateQuery->expr()->eq('propertypath', $updateQuery->createParameter('propertyPath')))
439+
->andWhere($updateQuery->expr()->eq('propertyname', $updateQuery->createParameter('propertyName')));
440+
return $updateQuery;
441+
}
420442
}

0 commit comments

Comments
 (0)