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
7 changes: 6 additions & 1 deletion apps/contactsinteraction/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<name>Contacts Interaction</name>
<summary>Manages interaction between accounts and contacts</summary>
<description>Collect data about accounts and contacts interactions and provide an address book for the data</description>
<version>1.12.0</version>
<version>1.12.1</version>
<licence>agpl</licence>
<author>Christoph Wurst</author>
<author homepage="https://github.com/nextcloud/groupware">Nextcloud Groupware Team</author>
Expand All @@ -26,6 +26,11 @@
<background-jobs>
<job>OCA\ContactsInteraction\BackgroundJob\CleanupJob</job>
</background-jobs>
<repair-steps>
<live-migration>
<step>OCA\ContactsInteraction\Migration\FixVcardCategory</step>
</live-migration>
</repair-steps>
<sabre>
<address-book-plugins>
<plugin>OCA\ContactsInteraction\AddressBookProvider</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
'OCA\\ContactsInteraction\\Db\\RecentContactMapper' => $baseDir . '/../lib/Db/RecentContactMapper.php',
'OCA\\ContactsInteraction\\Listeners\\ContactInteractionListener' => $baseDir . '/../lib/Listeners/ContactInteractionListener.php',
'OCA\\ContactsInteraction\\Listeners\\UserDeletedListener' => $baseDir . '/../lib/Listeners/UserDeletedListener.php',
'OCA\\ContactsInteraction\\Migration\\FixVcardCategory' => $baseDir . '/../lib/Migration/FixVcardCategory.php',
'OCA\\ContactsInteraction\\Migration\\Version010000Date20200304152605' => $baseDir . '/../lib/Migration/Version010000Date20200304152605.php',
);
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ComposerStaticInitContactsInteraction
'OCA\\ContactsInteraction\\Db\\RecentContactMapper' => __DIR__ . '/..' . '/../lib/Db/RecentContactMapper.php',
'OCA\\ContactsInteraction\\Listeners\\ContactInteractionListener' => __DIR__ . '/..' . '/../lib/Listeners/ContactInteractionListener.php',
'OCA\\ContactsInteraction\\Listeners\\UserDeletedListener' => __DIR__ . '/..' . '/../lib/Listeners/UserDeletedListener.php',
'OCA\\ContactsInteraction\\Migration\\FixVcardCategory' => __DIR__ . '/..' . '/../lib/Migration/FixVcardCategory.php',
'OCA\\ContactsInteraction\\Migration\\Version010000Date20200304152605' => __DIR__ . '/..' . '/../lib/Migration/Version010000Date20200304152605.php',
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ private function generateCard(RecentContact $contact): string {
$props = [
'URI' => UUIDUtil::getUUID(),
'FN' => $this->getDisplayName($contact->getUid()) ?? $contact->getEmail() ?? $contact->getFederatedCloudId(),
'CATEGORIES' => $this->l10n->t('Recently contacted'),
// Recently contacted not translated on purpose: https://github.com/nextcloud/contacts/issues/4663
'CATEGORIES' => 'Recently contacted',
];

if ($contact->getEmail() !== null) {
Expand Down
88 changes: 88 additions & 0 deletions apps/contactsinteraction/lib/Migration/FixVcardCategory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\ContactsInteraction\Migration;

use OC\Migration\BackgroundRepair;
use OCA\ContactsInteraction\AppInfo\Application;
use OCP\BackgroundJob\IJobList;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
use Sabre\VObject\ParseException;
use Sabre\VObject\Reader;

class FixVcardCategory implements IRepairStep {

private const CARDS_PER_BATCH = 5000;

public function __construct(
private readonly IDBConnection $connection,
private readonly IJobList $jobList,
) {
}

public function getName(): string {
return 'Fix category of recent contacts vcards';
}

public function run(IOutput $output): void {
$query = $this->connection->getQueryBuilder();

$cardsWithTranslatedCategory = $query->select(['id', 'card'])
->from('recent_contact')
->where($query->expr()->notLike(
'card',
$query->createNamedParameter('%CATEGORIES:Recently contacted%')
))
->setMaxResults(self::CARDS_PER_BATCH)
->executeQuery();
$rowCount = $cardsWithTranslatedCategory->rowCount();

$output->startProgress($rowCount);

$this->connection->beginTransaction();

$updateQuery = $query->update('recent_contact')
->set('card', $query->createParameter('card'))
->where($query->expr()->eq('id', $query->createParameter('id')));

while ($card = $cardsWithTranslatedCategory->fetch()) {
$output->advance(1);

try {
$vcard = Reader::read($card['card']);
} catch (ParseException $e) {
$output->info('Could not parse vcard with id ' . $card['id']);
continue;
}

$vcard->remove('CATEGORIES');
$vcard->add('CATEGORIES', 'Recently contacted');

$updateQuery->setParameter('id', $card['id']);
$updateQuery->setParameter('card', $vcard->serialize());
$updateQuery->executeStatement();
}

$this->connection->commit();

$cardsWithTranslatedCategory->closeCursor();

$output->finishProgress();

if ($rowCount === self::CARDS_PER_BATCH) {
$this->jobList->add(BackgroundRepair::class, [
'app' => Application::APP_ID,
'step' => FixVcardCategory::class,
'reschedule' => time(), // Use a different argument to reschedule the job
]);
}
}
}
Loading