@@ -23,9 +23,20 @@ $cm = \OC::$server->getContactsManager(); | |||
$cm->register(function() use ($cm) { | |||
$db = \OC::$server->getDatabaseConnection(); | |||
$userId = \OC::$server->getUserSession()->getUser()->getUID(); | |||
$cardDav = new \OCA\DAV\CardDAV\CardDavBackend($db); | |||
$principal = new \OCA\DAV\Connector\Sabre\Principal( | |||
\OC::$server->getConfig(), | |||
\OC::$server->getUserManager() | |||
); | |||
$cardDav = new \OCA\DAV\CardDAV\CardDavBackend($db, $principal, \OC::$server->getLogger()); | |||
$addressBooks = $cardDav->getAddressBooksForUser("principals/$userId"); | |||
foreach ($addressBooks as $addressBook) { | |||
$cm->registerAddressBook(new OCA\DAV\CardDAV\AddressBookImpl($addressBook)); | |||
foreach ($addressBooks as $addressBookInfo) { | |||
$addressBook = new \OCA\DAV\CardDAV\AddressBook($cardDav, $addressBookInfo); | |||
$cm->registerAddressBook( | |||
new OCA\DAV\CardDAV\AddressBookImpl( | |||
$addressBook, | |||
$addressBookInfo, | |||
$cardDav | |||
) | |||
); | |||
} | |||
}); |
@@ -571,6 +571,78 @@ CREATE TABLE calendarobjects ( | |||
</declaration> | |||
</table> | |||
<table> | |||
<name>*dbprefix*cards_properties</name> | |||
<declaration> | |||
<field> | |||
<name>id</name> | |||
<type>integer</type> | |||
<default>0</default> | |||
<notnull>true</notnull> | |||
<autoincrement>1</autoincrement> | |||
<unsigned>true</unsigned> | |||
<length>11</length> | |||
</field> | |||
<field> | |||
<name>addressbookid</name> | |||
<type>integer</type> | |||
<default></default> | |||
<notnull>true</notnull> | |||
<length>11</length> | |||
</field> | |||
<field> | |||
<name>cardid</name> | |||
<type>integer</type> | |||
<default></default> | |||
<notnull>true</notnull> | |||
<unsigned>true</unsigned> | |||
<length>11</length> | |||
</field> | |||
<field> | |||
<name>name</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>64</length> | |||
</field> | |||
<field> | |||
<name>value</name> | |||
<type>text</type> | |||
<default></default> | |||
<notnull>false</notnull> | |||
<length>255</length> | |||
</field> | |||
<field> | |||
<name>preferred</name> | |||
<type>integer</type> | |||
<default>1</default> | |||
<notnull>true</notnull> | |||
<length>4</length> | |||
</field> | |||
<index> | |||
<name>card_contactid_index</name> | |||
<field> | |||
<name>cardid</name> | |||
<sorting>ascending</sorting> | |||
</field> | |||
</index> | |||
<index> | |||
<name>card_name_index</name> | |||
<field> | |||
<name>name</name> | |||
<sorting>ascending</sorting> | |||
</field> | |||
</index> | |||
<index> | |||
<name>card_value_index</name> | |||
<field> | |||
<name>value</name> | |||
<sorting>ascending</sorting> | |||
</field> | |||
</index> | |||
</declaration> | |||
</table> | |||
<table> | |||
<name>*dbprefix*dav_shares</name> | |||
<declaration> |
@@ -8,8 +8,9 @@ $config = \OC::$server->getConfig(); | |||
$dbConnection = \OC::$server->getDatabaseConnection(); | |||
$userManager = OC::$server->getUserManager(); | |||
$config = \OC::$server->getConfig(); | |||
$logger = \OC::$server->getLogger(); | |||
/** @var Symfony\Component\Console\Application $application */ | |||
$application->add(new CreateAddressBook($userManager, $dbConnection, $config)); | |||
$application->add(new CreateAddressBook($userManager, $dbConnection, $config, $logger)); | |||
$application->add(new CreateCalendar($userManager, $dbConnection)); | |||
$application->add(new SyncSystemAddressBook($userManager, $dbConnection, $config)); |
@@ -6,6 +6,7 @@ use OCA\DAV\CardDAV\CardDavBackend; | |||
use OCA\DAV\Connector\Sabre\Principal; | |||
use OCP\IConfig; | |||
use OCP\IDBConnection; | |||
use OCP\ILogger; | |||
use OCP\IUserManager; | |||
use Symfony\Component\Console\Command\Command; | |||
use Symfony\Component\Console\Input\InputArgument; | |||
@@ -23,15 +24,25 @@ class CreateAddressBook extends Command { | |||
/** @var IConfig */ | |||
private $config; | |||
/** @var ILogger */ | |||
private $logger; | |||
/** | |||
* @param IUserManager $userManager | |||
* @param IDBConnection $dbConnection | |||
* @param IConfig $config | |||
* @param ILogger $logger | |||
*/ | |||
function __construct(IUserManager $userManager, IDBConnection $dbConnection, IConfig $config) { | |||
function __construct(IUserManager $userManager, | |||
IDBConnection $dbConnection, | |||
IConfig $config, | |||
ILogger $logger | |||
) { | |||
parent::__construct(); | |||
$this->userManager = $userManager; | |||
$this->dbConnection = $dbConnection; | |||
$this->config = $config; | |||
$this->logger = $logger; | |||
} | |||
protected function configure() { |
@@ -1,100 +0,0 @@ | |||
<?php | |||
/** | |||
* @author Thomas Müller <thomas.mueller@tmit.eu> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* 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, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\DAV\CardDAV; | |||
class AddressBookImpl implements \OCP\IAddressBook { | |||
public function __construct(array $values, CardDavBackend $backend) { | |||
$this->values = $values; | |||
$this->backend = $backend; | |||
/* | |||
* 'id' => $row['id'], | |||
'uri' => $row['uri'], | |||
'principaluri' => $row['principaluri'], | |||
'{DAV:}displayname' => $row['displayname'], | |||
'{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], | |||
'{http://calendarserver.org/ns/}getctag' => $row['synctoken'], | |||
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0', | |||
*/ | |||
} | |||
/** | |||
* @return string defining the technical unique key | |||
* @since 5.0.0 | |||
*/ | |||
public function getKey() { | |||
return $this->values['id']; | |||
} | |||
/** | |||
* In comparison to getKey() this function returns a human readable (maybe translated) name | |||
* | |||
* @return mixed | |||
* @since 5.0.0 | |||
*/ | |||
public function getDisplayName() { | |||
return $this->values['{DAV:}displayname']; | |||
} | |||
/** | |||
* @param string $pattern which should match within the $searchProperties | |||
* @param array $searchProperties defines the properties within the query pattern should match | |||
* @param array $options - for future use. One should always have options! | |||
* @return array an array of contacts which are arrays of key-value-pairs | |||
* @since 5.0.0 | |||
*/ | |||
public function search($pattern, $searchProperties, $options) { | |||
// TODO: Implement search() method. | |||
$cards = $this->backend->getCards($this->values['id']); | |||
// | |||
// TODO: search now | |||
// | |||
} | |||
/** | |||
* @param array $properties this array if key-value-pairs defines a contact | |||
* @return array an array representing the contact just created or updated | |||
* @since 5.0.0 | |||
*/ | |||
public function createOrUpdate($properties) { | |||
// TODO: Implement createOrUpdate() method. | |||
} | |||
/** | |||
* @return mixed | |||
* @since 5.0.0 | |||
*/ | |||
public function getPermissions() { | |||
// TODO: Implement getPermissions() method. | |||
} | |||
/** | |||
* @param object $id the unique identifier to a contact | |||
* @return bool successful or not | |||
* @since 5.0.0 | |||
*/ | |||
public function delete($id) { | |||
// TODO: Implement delete() method. | |||
} | |||
} |
@@ -0,0 +1,219 @@ | |||
<?php | |||
/** | |||
* @author Thomas Müller <thomas.mueller@tmit.eu> | |||
* @author Björn Schießle <schiessle@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* 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, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\DAV\CardDAV; | |||
use OCP\Constants; | |||
use OCP\IAddressBook; | |||
use Sabre\VObject\Component\VCard; | |||
use Sabre\VObject\Property\Text; | |||
use Sabre\VObject\Reader; | |||
use Sabre\VObject\UUIDUtil; | |||
class AddressBookImpl implements IAddressBook { | |||
/** @var CardDavBackend */ | |||
private $backend; | |||
/** @var array */ | |||
private $addressBookInfo; | |||
/** @var AddressBook */ | |||
private $addressBook; | |||
/** | |||
* AddressBookImpl constructor. | |||
* | |||
* @param AddressBook $addressBook | |||
* @param array $addressBookInfo | |||
* @param CardDavBackend $backend | |||
*/ | |||
public function __construct( | |||
AddressBook $addressBook, | |||
array $addressBookInfo, | |||
CardDavBackend $backend) { | |||
$this->addressBook = $addressBook; | |||
$this->addressBookInfo = $addressBookInfo; | |||
$this->backend = $backend; | |||
} | |||
/** | |||
* @return string defining the technical unique key | |||
* @since 5.0.0 | |||
*/ | |||
public function getKey() { | |||
return $this->addressBookInfo['id']; | |||
} | |||
/** | |||
* In comparison to getKey() this function returns a human readable (maybe translated) name | |||
* | |||
* @return mixed | |||
* @since 5.0.0 | |||
*/ | |||
public function getDisplayName() { | |||
return $this->addressBookInfo['{DAV:}displayname']; | |||
} | |||
/** | |||
* @param string $pattern which should match within the $searchProperties | |||
* @param array $searchProperties defines the properties within the query pattern should match | |||
* @param array $options - for future use. One should always have options! | |||
* @return array an array of contacts which are arrays of key-value-pairs | |||
* @since 5.0.0 | |||
*/ | |||
public function search($pattern, $searchProperties, $options) { | |||
$result = $this->backend->search($this->getKey(), $pattern, $searchProperties); | |||
$vCards = []; | |||
foreach ($result as $cardData) { | |||
$vCards[] = $this->vCard2Array($this->readCard($cardData)); | |||
} | |||
return $vCards; | |||
} | |||
/** | |||
* @param array $properties this array if key-value-pairs defines a contact | |||
* @return array an array representing the contact just created or updated | |||
* @since 5.0.0 | |||
*/ | |||
public function createOrUpdate($properties) { | |||
$update = false; | |||
if (!isset($properties['UID'])) { // create a new contact | |||
$uid = $this->createUid(); | |||
$uri = $uid . '.vcf'; | |||
$vCard = $this->createEmptyVCard($uid); | |||
} else { // update existing contact | |||
$uid = $properties['UID']; | |||
$uri = $uid . '.vcf'; | |||
$vCardData = $this->backend->getCard($this->getKey(), $uri); | |||
$vCard = $this->readCard($vCardData['carddata']); | |||
$update = true; | |||
} | |||
foreach ($properties as $key => $value) { | |||
$vCard->$key = $vCard->createProperty($key, $value); | |||
} | |||
if ($update) { | |||
$this->backend->updateCard($this->getKey(), $uri, $vCard->serialize()); | |||
} else { | |||
$this->backend->createCard($this->getKey(), $uri, $vCard->serialize()); | |||
} | |||
return $this->vCard2Array($vCard); | |||
} | |||
/** | |||
* @return mixed | |||
* @since 5.0.0 | |||
*/ | |||
public function getPermissions() { | |||
$permissions = $this->addressBook->getACL(); | |||
$result = 0; | |||
foreach ($permissions as $permission) { | |||
switch($permission['privilege']) { | |||
case '{DAV:}read': | |||
$result |= Constants::PERMISSION_READ; | |||
break; | |||
case '{DAV:}write': | |||
$result |= Constants::PERMISSION_CREATE; | |||
$result |= Constants::PERMISSION_UPDATE; | |||
break; | |||
case '{DAV:}all': | |||
$result |= Constants::PERMISSION_ALL; | |||
break; | |||
} | |||
} | |||
return $result; | |||
} | |||
/** | |||
* @param object $id the unique identifier to a contact | |||
* @return bool successful or not | |||
* @since 5.0.0 | |||
*/ | |||
public function delete($id) { | |||
$uri = $this->backend->getCardUri($id); | |||
return $this->backend->deleteCard($this->addressBookInfo['id'], $uri); | |||
} | |||
/** | |||
* read vCard data into a vCard object | |||
* | |||
* @param string $cardData | |||
* @return VCard | |||
*/ | |||
protected function readCard($cardData) { | |||
return Reader::read($cardData); | |||
} | |||
/** | |||
* create UID for contact | |||
* | |||
* @return string | |||
*/ | |||
protected function createUid() { | |||
do { | |||
$uid = $this->getUid(); | |||
} while (!empty($this->backend->getContact($uid . '.vcf'))); | |||
return $uid; | |||
} | |||
/** | |||
* getUid is only there for testing, use createUid instead | |||
*/ | |||
protected function getUid() { | |||
return UUIDUtil::getUUID(); | |||
} | |||
/** | |||
* create empty vcard | |||
* | |||
* @param string $uid | |||
* @return VCard | |||
*/ | |||
protected function createEmptyVCard($uid) { | |||
$vCard = new VCard(); | |||
$vCard->add(new Text($vCard, 'UID', $uid)); | |||
return $vCard; | |||
} | |||
/** | |||
* create array with all vCard properties | |||
* | |||
* @param VCard $vCard | |||
* @return array | |||
*/ | |||
protected function vCard2Array(VCard $vCard) { | |||
$result = []; | |||
foreach ($vCard->children as $property) { | |||
$result[$property->name] = $property->getValue(); | |||
} | |||
return $result; | |||
} | |||
} |
@@ -23,19 +23,47 @@ | |||
namespace OCA\DAV\CardDAV; | |||
use OCA\DAV\Connector\Sabre\Principal; | |||
use OCP\IDBConnection; | |||
use OCP\ILogger; | |||
use Sabre\CardDAV\Backend\BackendInterface; | |||
use Sabre\CardDAV\Backend\SyncSupport; | |||
use Sabre\CardDAV\Plugin; | |||
use Sabre\DAV\Exception\BadRequest; | |||
use Sabre\VObject\Reader; | |||
class CardDavBackend implements BackendInterface, SyncSupport { | |||
/** @var Principal */ | |||
private $principalBackend; | |||
public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) { | |||
/** @var ILogger */ | |||
private $logger; | |||
/** @var string */ | |||
private $dbCardsTable = 'cards'; | |||
/** @var string */ | |||
private $dbCardsPropertiesTable = 'cards_properties'; | |||
/** @var IDBConnection */ | |||
private $db; | |||
/** @var array properties to index */ | |||
public static $indexProperties = array( | |||
'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME', | |||
'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO', 'CLOUD'); | |||
/** | |||
* CardDavBackend constructor. | |||
* | |||
* @param IDBConnection $db | |||
* @param Principal $principalBackend | |||
* @param ILogger $logger | |||
*/ | |||
public function __construct(IDBConnection $db, Principal $principalBackend, ILogger $logger) { | |||
$this->db = $db; | |||
$this->principalBackend = $principalBackend; | |||
$this->logger = $logger; | |||
} | |||
/** | |||
@@ -263,6 +291,11 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBookId))) | |||
->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook'))) | |||
->execute(); | |||
$query->delete($this->dbCardsPropertiesTable) | |||
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) | |||
->execute(); | |||
} | |||
/** | |||
@@ -408,6 +441,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
->execute(); | |||
$this->addChange($addressBookId, $cardUri, 1); | |||
$this->updateProperties($addressBookId, $cardUri, $cardData); | |||
return '"' . $etag . '"'; | |||
} | |||
@@ -451,6 +485,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
->execute(); | |||
$this->addChange($addressBookId, $cardUri, 2); | |||
$this->updateProperties($addressBookId, $cardUri, $cardData); | |||
return '"' . $etag . '"'; | |||
} | |||
@@ -463,6 +498,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
* @return bool | |||
*/ | |||
function deleteCard($addressBookId, $cardUri) { | |||
$cardId = $this->getCardId($cardUri); | |||
$query = $this->db->getQueryBuilder(); | |||
$ret = $query->delete('cards') | |||
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) | |||
@@ -471,7 +507,12 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
$this->addChange($addressBookId, $cardUri, 3); | |||
return $ret === 1; | |||
if ($ret === 1) { | |||
$this->purgeProperties($addressBookId, $cardId); | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
@@ -637,6 +678,83 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
} | |||
} | |||
/** | |||
* search contact | |||
* | |||
* @param int $addressBookId | |||
* @param string $pattern which should match within the $searchProperties | |||
* @param array $searchProperties defines the properties within the query pattern should match | |||
* @return array an array of contacts which are arrays of key-value-pairs | |||
*/ | |||
public function search($addressBookId, $pattern, $searchProperties) { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->selectDistinct('carddata', 'c') | |||
->from($this->dbCardsTable, 'c') | |||
->leftJoin('c', $this->dbCardsPropertiesTable, 'cp', $query->expr()->eq('cp.cardid', 'c.id')); | |||
foreach ($searchProperties as $property) { | |||
$query->orWhere( | |||
$query->expr()->andX( | |||
$query->expr()->eq('cp.name', $query->createNamedParameter($property)), | |||
$query->expr()->like('cp.value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%')) | |||
) | |||
); | |||
} | |||
$query->andWhere($query->expr()->eq('cp.addressbookid', $query->createNamedParameter($addressBookId))); | |||
$result = $query->execute(); | |||
$cards = $result->fetchAll(); | |||
$result->closeCursor(); | |||
return array_map(function($array) {return $this->readBlob($array['carddata']);}, $cards); | |||
} | |||
/** | |||
* get URI from a given contact | |||
* | |||
* @param int $id | |||
* @return string | |||
*/ | |||
public function getCardUri($id) { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->select('uri')->from($this->dbCardsTable) | |||
->where($query->expr()->eq('id', $query->createParameter('id'))) | |||
->setParameter('id', $id); | |||
$result = $query->execute(); | |||
$uri = $result->fetch(); | |||
$result->closeCursor(); | |||
if (!isset($uri['uri'])) { | |||
throw new \InvalidArgumentException('Card does not exists: ' . $id); | |||
} | |||
return $uri['uri']; | |||
} | |||
/** | |||
* return contact with the given URI | |||
* | |||
* @param string $uri | |||
* @returns array | |||
*/ | |||
public function getContact($uri) { | |||
$result = []; | |||
$query = $this->db->getQueryBuilder(); | |||
$query->select('*')->from($this->dbCardsTable) | |||
->where($query->expr()->eq('uri', $query->createParameter('uri'))) | |||
->setParameter('uri', $uri); | |||
$queryResult = $query->execute(); | |||
$contact = $queryResult->fetch(); | |||
$queryResult->closeCursor(); | |||
if (is_array($contact)) { | |||
$result = $contact; | |||
} | |||
return $result; | |||
} | |||
/** | |||
* @param string $addressBookUri | |||
* @param string $element | |||
@@ -734,4 +852,93 @@ class CardDavBackend implements BackendInterface, SyncSupport { | |||
return $shares; | |||
} | |||
/** | |||
* update properties table | |||
* | |||
* @param int $addressBookId | |||
* @param string $cardUri | |||
* @param string $vCardSerialized | |||
*/ | |||
protected function updateProperties($addressBookId, $cardUri, $vCardSerialized) { | |||
$cardId = $this->getCardId($cardUri); | |||
$vCard = $this->readCard($vCardSerialized); | |||
$this->purgeProperties($addressBookId, $cardId); | |||
$query = $this->db->getQueryBuilder(); | |||
$query->insert($this->dbCardsPropertiesTable) | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter($addressBookId), | |||
'cardid' => $query->createNamedParameter($cardId), | |||
'name' => $query->createParameter('name'), | |||
'value' => $query->createParameter('value'), | |||
'preferred' => $query->createParameter('preferred') | |||
] | |||
); | |||
foreach ($vCard->children as $property) { | |||
if(!in_array($property->name, self::$indexProperties)) { | |||
continue; | |||
} | |||
$preferred = 0; | |||
foreach($property->parameters as $parameter) { | |||
if ($parameter->name == 'TYPE' && strtoupper($parameter->getValue()) == 'PREF') { | |||
$preferred = 1; | |||
break; | |||
} | |||
} | |||
$query->setParameter('name', $property->name); | |||
$query->setParameter('value', substr($property->getValue(), 0, 254)); | |||
$query->setParameter('preferred', $preferred); | |||
$query->execute(); | |||
} | |||
} | |||
/** | |||
* read vCard data into a vCard object | |||
* | |||
* @param string $cardData | |||
* @return VCard | |||
*/ | |||
protected function readCard($cardData) { | |||
return Reader::read($cardData); | |||
} | |||
/** | |||
* delete all properties from a given card | |||
* | |||
* @param int $addressBookId | |||
* @param int $cardId | |||
*/ | |||
protected function purgeProperties($addressBookId, $cardId) { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->delete($this->dbCardsPropertiesTable) | |||
->where($query->expr()->eq('cardid', $query->createNamedParameter($cardId))) | |||
->andWhere($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); | |||
$query->execute(); | |||
} | |||
/** | |||
* get ID from a given contact | |||
* | |||
* @param string $uri | |||
* @return int | |||
*/ | |||
protected function getCardId($uri) { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->select('id')->from($this->dbCardsTable) | |||
->where($query->expr()->eq('uri', $query->createNamedParameter($uri))); | |||
$result = $query->execute(); | |||
$cardIds = $result->fetch(); | |||
$result->closeCursor(); | |||
if (!isset($cardIds['id'])) { | |||
throw new \InvalidArgumentException('Card does not exists: ' . $uri); | |||
} | |||
return (int)$cardIds['id']; | |||
} | |||
} |
@@ -41,11 +41,11 @@ class RootCollection extends SimpleCollection { | |||
\OC::$server->getSystemTagObjectMapper() | |||
); | |||
$usersCardDavBackend = new CardDavBackend($db, $principalBackend); | |||
$usersCardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getLogger()); | |||
$usersAddressBookRoot = new AddressBookRoot($principalBackend, $usersCardDavBackend, 'principals/users'); | |||
$usersAddressBookRoot->disableListing = $disableListing; | |||
$systemCardDavBackend = new CardDavBackend($db, $principalBackend); | |||
$systemCardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getLogger()); | |||
$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, 'principals/system'); | |||
$systemAddressBookRoot->disableListing = $disableListing; | |||
@@ -0,0 +1,287 @@ | |||
<?php | |||
/** | |||
* @author Björn Schießle <schiessle@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* 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, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\DAV\Tests\Unit\CardDAV; | |||
use OCA\DAV\CardDAV\AddressBook; | |||
use OCA\DAV\CardDAV\AddressBookImpl; | |||
use OCA\DAV\CardDAV\CardDavBackend; | |||
use Sabre\VObject\Component\VCard; | |||
use Sabre\VObject\Property\Text; | |||
use Test\TestCase; | |||
class AddressBookImplTest extends TestCase { | |||
/** @var AddressBookImpl */ | |||
private $addressBookImpl; | |||
/** @var array */ | |||
private $addressBookInfo; | |||
/** @var AddressBook | \PHPUnit_Framework_MockObject_MockObject */ | |||
private $addressBook; | |||
/** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */ | |||
private $backend; | |||
/** @var VCard | \PHPUnit_Framework_MockObject_MockObject */ | |||
private $vCard; | |||
public function setUp() { | |||
parent::setUp(); | |||
$this->addressBookInfo = [ | |||
'id' => 42, | |||
'{DAV:}displayname' => 'display name' | |||
]; | |||
$this->addressBook = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBook') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->backend = $this->getMockBuilder('\OCA\DAV\CardDAV\CardDavBackend') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->vCard = $this->getMock('Sabre\VObject\Component\VCard'); | |||
$this->addressBookImpl = new AddressBookImpl( | |||
$this->addressBook, | |||
$this->addressBookInfo, | |||
$this->backend | |||
); | |||
} | |||
public function testGetKey() { | |||
$this->assertSame($this->addressBookInfo['id'], | |||
$this->addressBookImpl->getKey()); | |||
} | |||
public function testGetDisplayName() { | |||
$this->assertSame($this->addressBookInfo['{DAV:}displayname'], | |||
$this->addressBookImpl->getDisplayName()); | |||
} | |||
public function testSearch() { | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ | |||
$addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') | |||
->setConstructorArgs( | |||
[ | |||
$this->addressBook, | |||
$this->addressBookInfo, | |||
$this->backend | |||
] | |||
) | |||
->setMethods(['vCard2Array', 'readCard']) | |||
->getMock(); | |||
$pattern = 'pattern'; | |||
$searchProperties = 'properties'; | |||
$this->backend->expects($this->once())->method('search') | |||
->with($this->addressBookInfo['id'], $pattern, $searchProperties) | |||
->willReturn( | |||
[ | |||
'cardData1', | |||
'cardData2' | |||
] | |||
); | |||
$addressBookImpl->expects($this->exactly(2))->method('readCard') | |||
->willReturn($this->vCard); | |||
$addressBookImpl->expects($this->exactly(2))->method('vCard2Array') | |||
->with($this->vCard)->willReturn('vCard'); | |||
$result = $addressBookImpl->search($pattern, $searchProperties, []); | |||
$this->assertTrue((is_array($result))); | |||
$this->assertSame(2, count($result)); | |||
} | |||
/** | |||
* @dataProvider dataTestCreate | |||
* | |||
* @param array $properties | |||
*/ | |||
public function testCreate($properties) { | |||
$uid = 'uid'; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ | |||
$addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') | |||
->setConstructorArgs( | |||
[ | |||
$this->addressBook, | |||
$this->addressBookInfo, | |||
$this->backend | |||
] | |||
) | |||
->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard']) | |||
->getMock(); | |||
$addressBookImpl->expects($this->once())->method('createUid') | |||
->willReturn($uid); | |||
$addressBookImpl->expects($this->once())->method('createEmptyVCard') | |||
->with($uid)->willReturn($this->vCard); | |||
$this->vCard->expects($this->exactly(count($properties))) | |||
->method('createProperty'); | |||
$this->backend->expects($this->once())->method('createCard'); | |||
$this->backend->expects($this->never())->method('updateCard'); | |||
$this->backend->expects($this->never())->method('getCard'); | |||
$addressBookImpl->expects($this->once())->method('vCard2Array') | |||
->with($this->vCard)->willReturn(true); | |||
$this->assertTrue($addressBookImpl->createOrUpdate($properties)); | |||
} | |||
public function dataTestCreate() { | |||
return [ | |||
[[]], | |||
[['FN' => 'John Doe']] | |||
]; | |||
} | |||
public function testUpdate() { | |||
$uid = 'uid'; | |||
$properties = ['UID' => $uid, 'FN' => 'John Doe']; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ | |||
$addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') | |||
->setConstructorArgs( | |||
[ | |||
$this->addressBook, | |||
$this->addressBookInfo, | |||
$this->backend | |||
] | |||
) | |||
->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard']) | |||
->getMock(); | |||
$addressBookImpl->expects($this->never())->method('createUid'); | |||
$addressBookImpl->expects($this->never())->method('createEmptyVCard'); | |||
$this->backend->expects($this->once())->method('getCard') | |||
->with($this->addressBookInfo['id'], $uid . '.vcf') | |||
->willReturn(['carddata' => 'data']); | |||
$addressBookImpl->expects($this->once())->method('readCard') | |||
->with('data')->willReturn($this->vCard); | |||
$this->vCard->expects($this->exactly(count($properties))) | |||
->method('createProperty'); | |||
$this->backend->expects($this->never())->method('createCard'); | |||
$this->backend->expects($this->once())->method('updateCard'); | |||
$addressBookImpl->expects($this->once())->method('vCard2Array') | |||
->with($this->vCard)->willReturn(true); | |||
$this->assertTrue($addressBookImpl->createOrUpdate($properties)); | |||
} | |||
/** | |||
* @dataProvider dataTestGetPermissions | |||
* | |||
* @param array $permissions | |||
* @param int $expected | |||
*/ | |||
public function testGetPermissions($permissions, $expected) { | |||
$this->addressBook->expects($this->once())->method('getACL') | |||
->willReturn($permissions); | |||
$this->assertSame($expected, | |||
$this->addressBookImpl->getPermissions() | |||
); | |||
} | |||
public function dataTestGetPermissions() { | |||
return [ | |||
[[], 0], | |||
[[['privilege' => '{DAV:}read']], 1], | |||
[[['privilege' => '{DAV:}write']], 6], | |||
[[['privilege' => '{DAV:}all']], 31], | |||
[[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 7], | |||
[[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}all']], 31], | |||
[[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}write']], 31], | |||
[[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write'],['privilege' => '{DAV:}all']], 31], | |||
[[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 31], | |||
]; | |||
} | |||
public function testDelete() { | |||
$cardId = 1; | |||
$cardUri = 'cardUri'; | |||
$this->backend->expects($this->once())->method('getCardUri') | |||
->with($cardId)->willReturn($cardUri); | |||
$this->backend->expects($this->once())->method('deleteCard') | |||
->with($this->addressBookInfo['id'], $cardUri) | |||
->willReturn(true); | |||
$this->assertTrue($this->addressBookImpl->delete($cardId)); | |||
} | |||
public function testReadCard() { | |||
$vCard = new VCard(); | |||
$vCard->add(new Text($vCard, 'UID', 'uid')); | |||
$vCardSerialized = $vCard->serialize(); | |||
$result = $this->invokePrivate($this->addressBookImpl, 'readCard', [$vCardSerialized]); | |||
$resultSerialized = $result->serialize(); | |||
$this->assertSame($vCardSerialized, $resultSerialized); | |||
} | |||
public function testCreateUid() { | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */ | |||
$addressBookImpl = $this->getMockBuilder('OCA\DAV\CardDAV\AddressBookImpl') | |||
->setConstructorArgs( | |||
[ | |||
$this->addressBook, | |||
$this->addressBookInfo, | |||
$this->backend | |||
] | |||
) | |||
->setMethods(['getUid']) | |||
->getMock(); | |||
$addressBookImpl->expects($this->at(0))->method('getUid')->willReturn('uid0'); | |||
$addressBookImpl->expects($this->at(1))->method('getUid')->willReturn('uid1'); | |||
// simulate that 'uid0' already exists, so the second uid will be returned | |||
$this->backend->expects($this->exactly(2))->method('getContact') | |||
->willReturnCallback( | |||
function($uid) { | |||
return ($uid === 'uid0.vcf'); | |||
} | |||
); | |||
$this->assertSame('uid1', | |||
$this->invokePrivate($addressBookImpl, 'createUid', []) | |||
); | |||
} | |||
public function testCreateEmptyVCard() { | |||
$uid = 'uid'; | |||
$expectedVCard = new VCard(); | |||
$expectedVCard->add(new Text($expectedVCard, 'UID', $uid)); | |||
$expectedVCardSerialized = $expectedVCard->serialize(); | |||
$result = $this->invokePrivate($this->addressBookImpl, 'createEmptyVCard', [$uid]); | |||
$resultSerialized = $result->serialize(); | |||
$this->assertSame($expectedVCardSerialized, $resultSerialized); | |||
} | |||
} |
@@ -21,7 +21,12 @@ | |||
namespace OCA\DAV\Tests\Unit\CardDAV; | |||
use OCA\DAV\CardDAV\CardDavBackend; | |||
use OCA\DAV\Connector\Sabre\Principal; | |||
use OCP\IDBConnection; | |||
use OCP\ILogger; | |||
use Sabre\DAV\PropPatch; | |||
use Sabre\VObject\Component\VCard; | |||
use Sabre\VObject\Property\Text; | |||
use Test\TestCase; | |||
/** | |||
@@ -36,22 +41,46 @@ class CardDavBackendTest extends TestCase { | |||
/** @var CardDavBackend */ | |||
private $backend; | |||
/** @var Principal | \PHPUnit_Framework_MockObject_MockObject */ | |||
private $principal; | |||
/** @var ILogger | \PHPUnit_Framework_MockObject_MockObject */ | |||
private $logger; | |||
/** @var IDBConnection */ | |||
private $db; | |||
/** @var string */ | |||
private $dbCardsTable = 'cards'; | |||
/** @var string */ | |||
private $dbCardsPropertiesTable = 'cards_properties'; | |||
const UNIT_TEST_USER = 'carddav-unit-test'; | |||
public function setUp() { | |||
parent::setUp(); | |||
$principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal') | |||
$this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal') | |||
->disableOriginalConstructor() | |||
->setMethods(['getPrincipalByPath']) | |||
->getMock(); | |||
$principal->method('getPrincipalByPath') | |||
$this->principal->method('getPrincipalByPath') | |||
->willReturn([ | |||
'uri' => 'principals/best-friend' | |||
]); | |||
$this->logger = $this->getMock('\OCP\ILogger'); | |||
$this->db = \OC::$server->getDatabaseConnection(); | |||
$this->backend = new CardDavBackend($this->db, $this->principal, $this->logger); | |||
// start every test with a empty cards_properties and cards table | |||
$query = $this->db->getQueryBuilder(); | |||
$query->delete('cards_properties')->execute(); | |||
$query = $this->db->getQueryBuilder(); | |||
$query->delete('cards')->execute(); | |||
$db = \OC::$server->getDatabaseConnection(); | |||
$this->backend = new CardDavBackend($db, $principal); | |||
$this->tearDown(); | |||
} | |||
@@ -96,23 +125,31 @@ class CardDavBackendTest extends TestCase { | |||
} | |||
public function testCardOperations() { | |||
$backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') | |||
->setConstructorArgs([$this->db, $this->principal, $this->logger]) | |||
->setMethods(['updateProperties', 'purgeProperties'])->getMock(); | |||
// create a new address book | |||
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); | |||
$books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); | |||
$backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); | |||
$books = $backend->getAddressBooksForUser(self::UNIT_TEST_USER); | |||
$this->assertEquals(1, count($books)); | |||
$bookId = $books[0]['id']; | |||
// create a card | |||
$uri = $this->getUniqueID('card'); | |||
$this->backend->createCard($bookId, $uri, ''); | |||
// updateProperties is expected twice, once for createCard and once for updateCard | |||
$backend->expects($this->at(0))->method('updateProperties')->with($bookId, $uri, ''); | |||
$backend->expects($this->at(1))->method('updateProperties')->with($bookId, $uri, '***'); | |||
// create a card | |||
$backend->createCard($bookId, $uri, ''); | |||
// get all the cards | |||
$cards = $this->backend->getCards($bookId); | |||
$cards = $backend->getCards($bookId); | |||
$this->assertEquals(1, count($cards)); | |||
$this->assertEquals('', $cards[0]['carddata']); | |||
// get the cards | |||
$card = $this->backend->getCard($bookId, $uri); | |||
$card = $backend->getCard($bookId, $uri); | |||
$this->assertNotNull($card); | |||
$this->assertArrayHasKey('id', $card); | |||
$this->assertArrayHasKey('uri', $card); | |||
@@ -122,17 +159,23 @@ class CardDavBackendTest extends TestCase { | |||
$this->assertEquals('', $card['carddata']); | |||
// update the card | |||
$this->backend->updateCard($bookId, $uri, '***'); | |||
$card = $this->backend->getCard($bookId, $uri); | |||
$backend->updateCard($bookId, $uri, '***'); | |||
$card = $backend->getCard($bookId, $uri); | |||
$this->assertEquals('***', $card['carddata']); | |||
// delete the card | |||
$this->backend->deleteCard($bookId, $uri); | |||
$cards = $this->backend->getCards($bookId); | |||
$backend->expects($this->once())->method('purgeProperties')->with($bookId, $card['id']); | |||
$backend->deleteCard($bookId, $uri); | |||
$cards = $backend->getCards($bookId); | |||
$this->assertEquals(0, count($cards)); | |||
} | |||
public function testMultiCard() { | |||
$this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') | |||
->setConstructorArgs([$this->db, $this->principal, $this->logger]) | |||
->setMethods(['updateProperties'])->getMock(); | |||
// create a new address book | |||
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); | |||
$books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); | |||
@@ -175,6 +218,11 @@ class CardDavBackendTest extends TestCase { | |||
} | |||
public function testSyncSupport() { | |||
$this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') | |||
->setConstructorArgs([$this->db, $this->principal, $this->logger]) | |||
->setMethods(['updateProperties'])->getMock(); | |||
// create a new address book | |||
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); | |||
$books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); | |||
@@ -221,4 +269,258 @@ class CardDavBackendTest extends TestCase { | |||
$books = $this->backend->getAddressBooksForUser('principals/best-friend'); | |||
$this->assertEquals(0, count($books)); | |||
} | |||
public function testUpdateProperties() { | |||
$bookId = 42; | |||
$cardUri = 'card-uri'; | |||
$cardId = 2; | |||
$backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') | |||
->setConstructorArgs([$this->db, $this->principal, $this->logger]) | |||
->setMethods(['getCardId'])->getMock(); | |||
$backend->expects($this->any())->method('getCardId')->willReturn($cardId); | |||
// add properties for new vCard | |||
$vCard = new VCard(); | |||
$vCard->add(new Text($vCard, 'UID', $cardUri)); | |||
$vCard->add(new Text($vCard, 'FN', 'John Doe')); | |||
$this->invokePrivate($backend, 'updateProperties', [$bookId, $cardUri, $vCard->serialize()]); | |||
$query = $this->db->getQueryBuilder(); | |||
$result = $query->select('*')->from('cards_properties')->execute()->fetchAll(); | |||
$this->assertSame(2, count($result)); | |||
$this->assertSame('UID', $result[0]['name']); | |||
$this->assertSame($cardUri, $result[0]['value']); | |||
$this->assertSame($bookId, (int)$result[0]['addressbookid']); | |||
$this->assertSame($cardId, (int)$result[0]['cardid']); | |||
$this->assertSame('FN', $result[1]['name']); | |||
$this->assertSame('John Doe', $result[1]['value']); | |||
$this->assertSame($bookId, (int)$result[1]['addressbookid']); | |||
$this->assertSame($cardId, (int)$result[1]['cardid']); | |||
// update properties for existing vCard | |||
$vCard = new VCard(); | |||
$vCard->add(new Text($vCard, 'FN', 'John Doe')); | |||
$this->invokePrivate($backend, 'updateProperties', [$bookId, $cardUri, $vCard->serialize()]); | |||
$query = $this->db->getQueryBuilder(); | |||
$result = $query->select('*')->from('cards_properties')->execute()->fetchAll(); | |||
$this->assertSame(1, count($result)); | |||
$this->assertSame('FN', $result[0]['name']); | |||
$this->assertSame('John Doe', $result[0]['value']); | |||
$this->assertSame($bookId, (int)$result[0]['addressbookid']); | |||
$this->assertSame($cardId, (int)$result[0]['cardid']); | |||
} | |||
public function testPurgeProperties() { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->insert('cards_properties') | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(1), | |||
'cardid' => $query->createNamedParameter(1), | |||
'name' => $query->createNamedParameter('name1'), | |||
'value' => $query->createNamedParameter('value1'), | |||
'preferred' => $query->createNamedParameter(0) | |||
] | |||
); | |||
$query->execute(); | |||
$query = $this->db->getQueryBuilder(); | |||
$query->insert('cards_properties') | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(1), | |||
'cardid' => $query->createNamedParameter(2), | |||
'name' => $query->createNamedParameter('name2'), | |||
'value' => $query->createNamedParameter('value2'), | |||
'preferred' => $query->createNamedParameter(0) | |||
] | |||
); | |||
$query->execute(); | |||
$this->invokePrivate($this->backend, 'purgeProperties', [1, 1]); | |||
$query = $this->db->getQueryBuilder(); | |||
$result = $query->select('*')->from('cards_properties')->execute()->fetchAll(); | |||
$this->assertSame(1, count($result)); | |||
$this->assertSame(1 ,(int)$result[0]['addressbookid']); | |||
$this->assertSame(2 ,(int)$result[0]['cardid']); | |||
} | |||
public function testGetCardId() { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->insert('cards') | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(1), | |||
'carddata' => $query->createNamedParameter(''), | |||
'uri' => $query->createNamedParameter('uri'), | |||
'lastmodified' => $query->createNamedParameter(4738743), | |||
'etag' => $query->createNamedParameter('etag'), | |||
'size' => $query->createNamedParameter(120) | |||
] | |||
); | |||
$query->execute(); | |||
$id = $query->getLastInsertId(); | |||
$this->assertSame($id, | |||
$this->invokePrivate($this->backend, 'getCardId', ['uri'])); | |||
} | |||
/** | |||
* @expectedException InvalidArgumentException | |||
*/ | |||
public function testGetCardIdFailed() { | |||
$this->invokePrivate($this->backend, 'getCardId', ['uri']); | |||
} | |||
/** | |||
* @dataProvider dataTestSearch | |||
* | |||
* @param string $pattern | |||
* @param array $expected | |||
*/ | |||
public function testSearch($pattern, $expected) { | |||
$vCards = []; | |||
$vCards[0] = new VCard(); | |||
$vCards[0]->add(new Text($vCards[0], 'UID', 'uid')); | |||
$vCards[0]->add(new Text($vCards[0], 'FN', 'John Doe')); | |||
$vCards[1] = new VCard(); | |||
$vCards[1]->add(new Text($vCards[1], 'UID', 'uid')); | |||
$vCards[1]->add(new Text($vCards[1], 'FN', 'John M. Doe')); | |||
$vCardIds = []; | |||
$query = $this->db->getQueryBuilder(); | |||
for($i=0; $i<2; $i++) { | |||
$query->insert($this->dbCardsTable) | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(0), | |||
'carddata' => $query->createNamedParameter($vCards[$i]->serialize()), | |||
'uri' => $query->createNamedParameter('uri' . $i), | |||
'lastmodified' => $query->createNamedParameter(5489543), | |||
'etag' => $query->createNamedParameter('etag' . $i), | |||
'size' => $query->createNamedParameter(120), | |||
] | |||
); | |||
$query->execute(); | |||
$vCardIds[] = $query->getLastInsertId(); | |||
} | |||
$query->insert($this->dbCardsPropertiesTable) | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(0), | |||
'cardid' => $query->createNamedParameter($vCardIds[0]), | |||
'name' => $query->createNamedParameter('FN'), | |||
'value' => $query->createNamedParameter('John Doe'), | |||
'preferred' => $query->createNamedParameter(0) | |||
] | |||
); | |||
$query->execute(); | |||
$query->insert($this->dbCardsPropertiesTable) | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(0), | |||
'cardid' => $query->createNamedParameter($vCardIds[1]), | |||
'name' => $query->createNamedParameter('FN'), | |||
'value' => $query->createNamedParameter('John M. Doe'), | |||
'preferred' => $query->createNamedParameter(0) | |||
] | |||
); | |||
$query->execute(); | |||
$result = $this->backend->search(0, $pattern, ['FN']); | |||
// check result | |||
$this->assertSame(count($expected), count($result)); | |||
$found = []; | |||
foreach ($result as $r) { | |||
foreach ($expected as $exp) { | |||
if (strpos($r, $exp) > 0) { | |||
$found[$exp] = true; | |||
break; | |||
} | |||
} | |||
} | |||
$this->assertSame(count($expected), count($found)); | |||
} | |||
public function dataTestSearch() { | |||
return [ | |||
['John', ['John Doe', 'John M. Doe']], | |||
['M. Doe', ['John M. Doe']], | |||
['Do', ['John Doe', 'John M. Doe']] | |||
]; | |||
} | |||
public function testGetCardUri() { | |||
$query = $this->db->getQueryBuilder(); | |||
$query->insert($this->dbCardsTable) | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter(1), | |||
'carddata' => $query->createNamedParameter('carddata', \PDO::PARAM_LOB), | |||
'uri' => $query->createNamedParameter('uri'), | |||
'lastmodified' => $query->createNamedParameter(5489543), | |||
'etag' => $query->createNamedParameter('etag'), | |||
'size' => $query->createNamedParameter(120), | |||
] | |||
); | |||
$query->execute(); | |||
$id = $query->getLastInsertId(); | |||
$this->assertSame('uri', $this->backend->getCardUri($id)); | |||
} | |||
/** | |||
* @expectedException InvalidArgumentException | |||
*/ | |||
public function testGetCardUriFailed() { | |||
$this->backend->getCardUri(1); | |||
} | |||
public function testGetContact() { | |||
$query = $this->db->getQueryBuilder(); | |||
for($i=0; $i<2; $i++) { | |||
$query->insert($this->dbCardsTable) | |||
->values( | |||
[ | |||
'addressbookid' => $query->createNamedParameter($i), | |||
'carddata' => $query->createNamedParameter('carddata' . $i, \PDO::PARAM_LOB), | |||
'uri' => $query->createNamedParameter('uri' . $i), | |||
'lastmodified' => $query->createNamedParameter(5489543), | |||
'etag' => $query->createNamedParameter('etag' . $i), | |||
'size' => $query->createNamedParameter(120), | |||
] | |||
); | |||
$query->execute(); | |||
} | |||
$result = $this->backend->getContact('uri0'); | |||
$this->assertSame(7, count($result)); | |||
$this->assertSame(0, (int)$result['addressbookid']); | |||
$this->assertSame('uri0', $result['uri']); | |||
$this->assertSame(5489543, (int)$result['lastmodified']); | |||
$this->assertSame('etag0', $result['etag']); | |||
$this->assertSame(120, (int)$result['size']); | |||
} | |||
public function testGetContactFail() { | |||
$this->assertEmpty($this->backend->getContact('uri')); | |||
} | |||
} |