mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
fix: fix full addressbook sync with truncated results
Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
parent
af0069c00e
commit
e87645a78a
3 changed files with 57 additions and 12 deletions
|
|
@ -479,6 +479,13 @@ class CardDavBackend implements BackendInterface, SyncSupport {
|
|||
->from($this->dbCardsTable)
|
||||
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressbookId)));
|
||||
|
||||
return $this->getCardsFromQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
private function getCardsFromQuery(IQueryBuilder $query): array {
|
||||
$cards = [];
|
||||
|
||||
$result = $query->executeQuery();
|
||||
|
|
@ -1532,4 +1539,32 @@ class CardDavBackend implements BackendInterface, SyncSupport {
|
|||
// should already be handled, but just in case
|
||||
throw new BadRequest('vCard can not be empty');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all cards in an address book as needing to be validated
|
||||
*
|
||||
* This is done by setting the modified date to `null`, once a sync runs
|
||||
* the mtime will be set to a non-null value. Leaving all deleted items with
|
||||
* a null modified date.
|
||||
*/
|
||||
public function markCardsAsPending(int $addressBookId): void {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->update($this->dbCardsTable)
|
||||
->set('lastmodified', $query->createNamedParameter(null))
|
||||
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)))
|
||||
->executeStatement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function getPendingCards(int $addressBookId): array {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->select(['id', 'addressbookid', 'uri', 'lastmodified', 'etag', 'size', 'carddata', 'uid'])
|
||||
->from($this->dbCardsTable)
|
||||
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)))
|
||||
->andWhere($query->expr()->isNull('lastmodified'));
|
||||
|
||||
return $this->getCardsFromQuery($query);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ class SyncService {
|
|||
throw $ex;
|
||||
}
|
||||
|
||||
$received = [];
|
||||
// 3. apply changes
|
||||
// TODO: use multi-get for download
|
||||
foreach ($response['response'] as $resource => $status) {
|
||||
|
|
@ -86,15 +85,6 @@ class SyncService {
|
|||
}
|
||||
}
|
||||
|
||||
// when doing a full sync, remove any items in the local address book that aren't in the remote one
|
||||
if (!$syncToken) {
|
||||
$existingCards = $this->backend->getCards($addressBookId);
|
||||
$removedCards = array_filter($existingCards, fn (array $card) => !in_array($card['uri'], $received));
|
||||
foreach ($removedCards as $removedCard) {
|
||||
$this->backend->deleteCard($addressBookId, $removedCard['uri']);
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
$response['token'],
|
||||
$response['truncated'],
|
||||
|
|
@ -365,4 +355,15 @@ class SyncService {
|
|||
public static function getCardUri(IUser $user): string {
|
||||
return $user->getBackendClassName() . ':' . $user->getUID() . '.vcf';
|
||||
}
|
||||
|
||||
public function markCardsAsPending(int $addressBookId): void {
|
||||
$this->backend->markCardsAsPending($addressBookId);
|
||||
}
|
||||
|
||||
public function deletePendingCards(int $addressBookId): void {
|
||||
$cards = $this->backend->getPendingCards($addressBookId);
|
||||
foreach ($cards as $card) {
|
||||
$this->backend->deleteCard($addressBookId, $card['uri']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,12 @@ class SyncFederationAddressBooks {
|
|||
];
|
||||
|
||||
try {
|
||||
$syncToken = $oldSyncToken;
|
||||
$syncToken = $full ? null : $oldSyncToken;
|
||||
|
||||
$book = $this->syncService->ensureSystemAddressBookExists($targetPrincipal, $targetBookId, $targetBookProperties);
|
||||
if ($full) {
|
||||
$this->syncService->markCardsAsPending($book['id']);
|
||||
}
|
||||
|
||||
do {
|
||||
[$syncToken, $truncated] = $this->syncService->syncRemoteAddressBook(
|
||||
|
|
@ -59,13 +64,17 @@ class SyncFederationAddressBooks {
|
|||
$cardDavUser,
|
||||
$addressBookUrl,
|
||||
$sharedSecret,
|
||||
$full ? null : $syncToken,
|
||||
$syncToken,
|
||||
$targetBookId,
|
||||
$targetPrincipal,
|
||||
$targetBookProperties
|
||||
);
|
||||
} while ($truncated);
|
||||
|
||||
if ($full) {
|
||||
$this->syncService->deletePendingCards($book['id']);
|
||||
}
|
||||
|
||||
if ($syncToken !== $oldSyncToken) {
|
||||
$this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $syncToken);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue