migrate therinaldos.com data
Build & Deploy to DigitalOcean Space / build (push) Failing after 2m38s

This commit is contained in:
2024-05-05 15:50:45 -04:00
commit ef1ff240d4
23182 changed files with 3801898 additions and 0 deletions
@@ -0,0 +1,169 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction;
use Exception;
use OCA\ContactsInteraction\AppInfo\Application;
use OCA\ContactsInteraction\Db\RecentContact;
use OCA\ContactsInteraction\Db\RecentContactMapper;
use OCA\DAV\CardDAV\Integration\ExternalAddressBook;
use OCA\DAV\DAV\Sharing\Plugin;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\IL10N;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch;
use Sabre\DAVACL\ACLTrait;
use Sabre\DAVACL\IACL;
class AddressBook extends ExternalAddressBook implements IACL {
use ACLTrait;
public const URI = 'recent';
public function __construct(
private RecentContactMapper $mapper,
private IL10N $l10n,
private string $principalUri,
) {
parent::__construct(Application::APP_ID, self::URI);
}
/**
* @inheritDoc
* @throws Exception
*/
public function delete(): void {
throw new Exception("This addressbook is immutable");
}
/**
* @inheritDoc
* @throws Exception
*/
public function createFile($name, $data = null) {
throw new Exception("This addressbook is immutable");
}
/**
* @inheritDoc
* @throws NotFound
*/
public function getChild($name): Card {
try {
return new Card(
$this->mapper->find(
$this->getUid(),
(int)$name
),
$this->principalUri,
$this->getACL()
);
} catch (DoesNotExistException $ex) {
throw new NotFound("Contact does not exist: " . $ex->getMessage(), 0, $ex);
}
}
/**
* @inheritDoc
*/
public function getChildren(): array {
return array_map(
function (RecentContact $contact) {
return new Card(
$contact,
$this->principalUri,
$this->getACL()
);
},
$this->mapper->findAll($this->getUid())
);
}
/**
* @inheritDoc
*/
public function childExists($name): bool {
try {
$this->mapper->find(
$this->getUid(),
(int)$name
);
return true;
} catch (DoesNotExistException $e) {
return false;
}
}
/**
* @inheritDoc
*/
public function getLastModified(): ?int {
return $this->mapper->findLastUpdatedForUserId($this->getUid());
}
/**
* @inheritDoc
* @throws Exception
*/
public function propPatch(PropPatch $propPatch) {
throw new Exception("This addressbook is immutable");
}
/**
* @inheritDoc
*/
public function getProperties($properties): array {
return [
'principaluri' => $this->principalUri,
'{DAV:}displayname' => $this->l10n->t('Recently contacted'),
'{' . Plugin::NS_OWNCLOUD . '}read-only' => true,
'{' . \OCA\DAV\CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($this->getLastModified() ?? 0),
];
}
public function getOwner(): string {
return $this->principalUri;
}
/**
* @inheritDoc
*/
public function getACL(): array {
return [
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner(),
'protected' => true,
],
];
}
private function getUid(): string {
[, $uid] = \Sabre\Uri\split($this->principalUri);
return $uid;
}
}
@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction;
use OCA\ContactsInteraction\AppInfo\Application;
use OCA\ContactsInteraction\Db\RecentContactMapper;
use OCA\DAV\CardDAV\Integration\ExternalAddressBook;
use OCA\DAV\CardDAV\Integration\IAddressBookProvider;
use OCP\IL10N;
class AddressBookProvider implements IAddressBookProvider {
public function __construct(
private RecentContactMapper $mapper,
private IL10N $l10n,
) {
}
/**
* @inheritDoc
*/
public function getAppId(): string {
return Application::APP_ID;
}
/**
* @inheritDoc
*/
public function fetchAllForAddressBookHome(string $principalUri): array {
return [
new AddressBook($this->mapper, $this->l10n, $principalUri)
];
}
/**
* @inheritDoc
*/
public function hasAddressBookInAddressBookHome(string $principalUri, string $uri): bool {
return $uri === AddressBook::URI;
}
/**
* @inheritDoc
*/
public function getAddressBookInAddressBookHome(string $principalUri, string $uri): ?ExternalAddressBook {
if ($uri === AddressBook::URI) {
return new AddressBook($this->mapper, $this->l10n, $principalUri);
}
return null;
}
}
@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Morris Jobke <hey@morrisjobke.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\AppInfo;
use OCA\ContactsInteraction\Listeners\ContactInteractionListener;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Contacts\Events\ContactInteractedWithEvent;
class Application extends App implements IBootstrap {
public const APP_ID = 'contactsinteraction';
public function __construct() {
parent::__construct(self::APP_ID);
}
public function register(IRegistrationContext $context): void {
$context->registerEventListener(ContactInteractedWithEvent::class, ContactInteractionListener::class);
}
public function boot(IBootContext $context): void {
}
}
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\BackgroundJob;
use OCA\ContactsInteraction\Db\RecentContactMapper;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\TimedJob;
class CleanupJob extends TimedJob {
public function __construct(
ITimeFactory $time,
private RecentContactMapper $mapper,
) {
parent::__construct($time);
$this->setInterval(24 * 60 * 60);
$this->setTimeSensitivity(IJob::TIME_INSENSITIVE);
}
protected function run(mixed $argument): void {
$time = $this->time->getDateTime();
$time->modify('-7days');
$this->mapper->cleanUp($time->getTimestamp());
}
}
@@ -0,0 +1,129 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction;
use OCA\ContactsInteraction\Db\RecentContact;
use Sabre\CardDAV\ICard;
use Sabre\DAV\Exception\NotImplemented;
use Sabre\DAVACL\ACLTrait;
use Sabre\DAVACL\IACL;
class Card implements ICard, IACL {
use ACLTrait;
public function __construct(
private RecentContact $contact,
private string $principal,
private array $acls,
) {
}
/**
* @inheritDoc
*/
public function getOwner(): ?string {
return $this->principal;
}
/**
* @inheritDoc
*/
public function getACL(): array {
return $this->acls;
}
/**
* @inheritDoc
*/
public function setAcls(array $acls): void {
throw new NotImplemented();
}
/**
* @inheritDoc
*/
public function put($data): ?string {
throw new NotImplemented();
}
/**
* @inheritDoc
*/
public function get(): string {
return $this->contact->getCard();
}
/**
* @inheritDoc
*/
public function getContentType(): ?string {
return 'text/vcard; charset=utf-8';
}
/**
* @inheritDoc
*/
public function getETag(): ?string {
return '"' . md5((string) $this->getLastModified()) . '"';
}
/**
* @inheritDoc
*/
public function getSize(): int {
throw new NotImplemented();
}
/**
* @inheritDoc
*/
public function delete(): void {
throw new NotImplemented();
}
/**
* @inheritDoc
*/
public function getName(): string {
return (string) $this->contact->getId();
}
/**
* @inheritDoc
*/
public function setName($name): void {
throw new NotImplemented();
}
/**
* @inheritDoc
*/
public function getLastModified(): ?int {
return $this->contact->getLastContact();
}
}
@@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\Db;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUser;
use function is_resource;
use function stream_get_contents;
class CardSearchDao {
private IDBConnection $db;
public function __construct(IDBConnection $db) {
$this->db = $db;
}
public function findExisting(IUser $user,
?string $uid,
?string $email,
?string $cloudId): ?string {
$addressbooksQuery = $this->db->getQueryBuilder();
$cardQuery = $this->db->getQueryBuilder();
$propQuery = $this->db->getQueryBuilder();
$propOr = $propQuery->expr()->orX();
if ($uid !== null) {
$propOr->add($propQuery->expr()->andX(
$propQuery->expr()->eq('name', $cardQuery->createNamedParameter('UID')),
$propQuery->expr()->eq('value', $cardQuery->createNamedParameter($uid))
));
}
if ($email !== null) {
$propOr->add($propQuery->expr()->andX(
$propQuery->expr()->eq('name', $cardQuery->createNamedParameter('EMAIL')),
$propQuery->expr()->eq('value', $cardQuery->createNamedParameter($email))
));
}
if ($cloudId !== null) {
$propOr->add($propQuery->expr()->andX(
$propQuery->expr()->eq('name', $cardQuery->createNamedParameter('CLOUD')),
$propQuery->expr()->eq('value', $cardQuery->createNamedParameter($cloudId))
));
}
$addressbooksQuery->selectDistinct('id')
->from('addressbooks')
->where($addressbooksQuery->expr()->eq('principaluri', $cardQuery->createNamedParameter("principals/users/" . $user->getUID())));
$propQuery->selectDistinct('cardid')
->from('cards_properties')
->where($propQuery->expr()->in('addressbookid', $propQuery->createFunction($addressbooksQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY))
->andWhere($propOr)
->groupBy('cardid');
$cardQuery->select('carddata')
->from('cards')
->where($cardQuery->expr()->in('id', $cardQuery->createFunction($propQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY))
->andWhere($cardQuery->expr()->in('addressbookid', $cardQuery->createFunction($addressbooksQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY))
->setMaxResults(1);
$result = $cardQuery->execute();
/** @var string|resource|false $card */
$card = $result->fetchOne();
if ($card === false) {
return null;
}
if (is_resource($card)) {
return stream_get_contents($card);
}
return $card;
}
}
@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\Db;
use OCP\AppFramework\Db\Entity;
/**
* @method void setActorUid(string $uid)
* @method string|null getActorUid()
* @method void setUid(string $uid)
* @method string|null getUid()
* @method void setEmail(string $email)
* @method string|null getEmail()
* @method void setFederatedCloudId(string $federatedCloudId)
* @method string|null getFederatedCloudId()
* @method void setCard(string $card)
* @method string getCard()
* @method void setLastContact(int $lastContact)
* @method int getLastContact()
*/
class RecentContact extends Entity {
protected string $actorUid = '';
protected ?string $uid = null;
protected ?string $email = null;
protected ?string $federatedCloudId = null;
protected string $card = '';
protected int $lastContact = -1;
public function __construct() {
$this->addType('actorUid', 'string');
$this->addType('uid', 'string');
$this->addType('email', 'string');
$this->addType('federatedCloudId', 'string');
$this->addType('card', 'blob');
$this->addType('lastContact', 'int');
}
}
@@ -0,0 +1,131 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\Db;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
use OCP\IDBConnection;
use OCP\IUser;
/**
* @template-extends QBMapper<RecentContact>
*/
class RecentContactMapper extends QBMapper {
public const TABLE_NAME = 'recent_contact';
public function __construct(IDBConnection $db) {
parent::__construct($db, self::TABLE_NAME);
}
/**
* @return RecentContact[]
*/
public function findAll(string $uid): array {
$qb = $this->db->getQueryBuilder();
$select = $qb
->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('actor_uid', $qb->createNamedParameter($uid)));
return $this->findEntities($select);
}
/**
* @throws DoesNotExistException
*/
public function find(string $uid, int $id): RecentContact {
$qb = $this->db->getQueryBuilder();
$select = $qb
->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, $qb::PARAM_INT)))
->andWhere($qb->expr()->eq('actor_uid', $qb->createNamedParameter($uid)));
return $this->findEntity($select);
}
/**
* @return RecentContact[]
*/
public function findMatch(IUser $user,
?string $uid,
?string $email,
?string $cloudId): array {
$qb = $this->db->getQueryBuilder();
$or = $qb->expr()->orX();
if ($uid !== null) {
$or->add($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
}
if ($email !== null) {
$or->add($qb->expr()->eq('email', $qb->createNamedParameter($email)));
}
if ($cloudId !== null) {
$or->add($qb->expr()->eq('federated_cloud_id', $qb->createNamedParameter($cloudId)));
}
$select = $qb
->select('*')
->from($this->getTableName())
->where($or)
->andWhere($qb->expr()->eq('actor_uid', $qb->createNamedParameter($user->getUID())));
return $this->findEntities($select);
}
public function findLastUpdatedForUserId(string $uid): ?int {
$qb = $this->db->getQueryBuilder();
$select = $qb
->select('last_contact')
->from($this->getTableName())
->where($qb->expr()->eq('actor_uid', $qb->createNamedParameter($uid)))
->orderBy('last_contact', 'DESC')
->setMaxResults(1);
$cursor = $select->executeQuery();
$row = $cursor->fetch();
if ($row === false) {
return null;
}
return (int)$row['last_contact'];
}
public function cleanUp(int $olderThan): void {
$qb = $this->db->getQueryBuilder();
$delete = $qb
->delete($this->getTableName())
->where($qb->expr()->lt('last_contact', $qb->createNamedParameter($olderThan)));
$delete->executeStatement();
}
}
@@ -0,0 +1,148 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\Listeners;
use OCA\ContactsInteraction\Db\CardSearchDao;
use OCA\ContactsInteraction\Db\RecentContact;
use OCA\ContactsInteraction\Db\RecentContactMapper;
use OCP\AppFramework\Db\TTransactional;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Contacts\Events\ContactInteractedWithEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IDBConnection;
use OCP\IL10N;
use OCP\IUserManager;
use Psr\Log\LoggerInterface;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\UUIDUtil;
class ContactInteractionListener implements IEventListener {
use TTransactional;
public function __construct(
private RecentContactMapper $mapper,
private CardSearchDao $cardSearchDao,
private IUserManager $userManager,
private IDBConnection $dbConnection,
private ITimeFactory $timeFactory,
private IL10N $l10n,
private LoggerInterface $logger,
) {
}
public function handle(Event $event): void {
if (!($event instanceof ContactInteractedWithEvent)) {
return;
}
if ($event->getUid() === null && $event->getEmail() === null && $event->getFederatedCloudId() === null) {
$this->logger->warning("Contact interaction event has no user identifier set");
return;
}
if ($event->getUid() !== null && $event->getUid() === $event->getActor()->getUID()) {
$this->logger->info("Ignoring contact interaction with self");
return;
}
$this->atomic(function () use ($event) {
$uid = $event->getUid();
$email = $event->getEmail();
$federatedCloudId = $event->getFederatedCloudId();
$existingContact = $this->cardSearchDao->findExisting(
$event->getActor(),
$uid,
$email,
$federatedCloudId);
if ($existingContact !== null) {
return;
}
$existingRecentlyContacted = $this->mapper->findMatch(
$event->getActor(),
$uid,
$email,
$federatedCloudId
);
if (!empty($existingRecentlyContacted)) {
$now = $this->timeFactory->getTime();
foreach ($existingRecentlyContacted as $c) {
$c->setLastContact($now);
$this->mapper->update($c);
}
return;
}
$contact = new RecentContact();
$contact->setActorUid($event->getActor()->getUID());
if ($uid !== null) {
$contact->setUid($uid);
}
if ($email !== null) {
$contact->setEmail($email);
}
if ($federatedCloudId !== null) {
$contact->setFederatedCloudId($federatedCloudId);
}
$contact->setLastContact($this->timeFactory->getTime());
$contact->setCard($this->generateCard($contact));
$this->mapper->insert($contact);
}, $this->dbConnection);
}
private function getDisplayName(?string $uid): ?string {
if ($uid === null) {
return null;
}
if (($user = $this->userManager->get($uid)) === null) {
return null;
}
return $user->getDisplayName();
}
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'),
];
if ($contact->getEmail() !== null) {
$props['EMAIL'] = $contact->getEmail();
}
if ($contact->getFederatedCloudId() !== null) {
$props['CLOUD'] = $contact->getFederatedCloudId();
}
return (new VCard($props))->serialize();
}
}
@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ContactsInteraction\Migration;
use Closure;
use OCA\ContactsInteraction\Db\RecentContactMapper;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
class Version010000Date20200304152605 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*
* @return ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
$table = $schema->createTable(RecentContactMapper::TABLE_NAME);
$table->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
'length' => 4,
]);
$table->addColumn('actor_uid', 'string', [
'notnull' => true,
'length' => 64,
]);
$table->addColumn('uid', 'string', [
'notnull' => false,
'length' => 64,
]);
$table->addColumn('email', 'string', [
'notnull' => false,
'length' => 255,
]);
$table->addColumn('federated_cloud_id', 'string', [
'notnull' => false,
'length' => 255,
]);
$table->addColumn('card', 'blob', [
'notnull' => true,
]);
$table->addColumn('last_contact', 'integer', [
'notnull' => true,
'length' => 4,
]);
$table->setPrimaryKey(['id']);
// To find all recent entries
$table->addIndex(['actor_uid'], RecentContactMapper::TABLE_NAME . '_actor_uid');
// To find a specific entry
$table->addIndex(['id', 'actor_uid'], RecentContactMapper::TABLE_NAME . '_id_uid');
// To find all recent entries with a given UID
$table->addIndex(['uid'], RecentContactMapper::TABLE_NAME . '_uid');
// To find all recent entries with a given email address
$table->addIndex(['email'], RecentContactMapper::TABLE_NAME . '_email');
// To find all recent entries with a give federated cloud id
$table->addIndex(['federated_cloud_id'], RecentContactMapper::TABLE_NAME . '_fed_id');
// For the cleanup
$table->addIndex(['last_contact'], RecentContactMapper::TABLE_NAME . '_last_contact');
return $schema;
}
}