mirror of
https://github.com/owncloudarchive/contacts.git
synced 2024-12-01 13:24:10 +01:00
Contacts: More updates on backends
This commit is contained in:
parent
da0b072e88
commit
3eb5303c3e
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Thomas Tanghus <thomas@tanghus.net>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
|
||||
OCP\JSON::checkLoggedIn();
|
||||
OCP\JSON::checkAppEnabled('contacts');
|
||||
|
||||
$catmgr = OCA\Contacts\App::getVCategories();
|
||||
$categories = $catmgr->categories(OC_VCategories::FORMAT_MAP);
|
||||
foreach($categories as &$category) {
|
||||
$ids = array();
|
||||
$contacts = $catmgr->itemsForCategory(
|
||||
$category['name'],
|
||||
array(
|
||||
'tablename' => '*PREFIX*contacts_cards',
|
||||
'fields' => array('id',),
|
||||
));
|
||||
foreach($contacts as $contact) {
|
||||
$ids[] = $contact['id'];
|
||||
}
|
||||
$category['contacts'] = $ids;
|
||||
}
|
||||
|
||||
$favorites = $catmgr->getFavorites();
|
||||
|
||||
OCP\JSON::success(array(
|
||||
'data' => array(
|
||||
'categories' => $categories,
|
||||
'favorites' => $favorites,
|
||||
'shared' => OCP\Share::getItemsSharedWith('addressbook', OCA\Contacts\Share_Backend_Addressbook::FORMAT_ADDRESSBOOKS),
|
||||
'lastgroup' => OCP\Config::getUserValue(
|
||||
OCP\User::getUser(),
|
||||
'contacts',
|
||||
'lastgroup', 'all'),
|
||||
'sortorder' => OCP\Config::getUserValue(
|
||||
OCP\User::getUser(),
|
||||
'contacts',
|
||||
'groupsort', ''),
|
||||
)
|
||||
)
|
||||
);
|
@ -43,7 +43,9 @@ if(!is_null($bookid)) {
|
||||
}
|
||||
} elseif(!is_null($contactid)) {
|
||||
try {
|
||||
$data = OCA\Contacts\VCard::find($contactid);
|
||||
$app = new OCA\Contacts\App();
|
||||
$contact = $app->getContact($_GET['backend'], $_GET['parent'], $_GET['contactid']);
|
||||
$data = $contact->serialize();
|
||||
} catch(Exception $e) {
|
||||
OCP\JSON::error(
|
||||
array(
|
||||
@ -56,8 +58,8 @@ if(!is_null($bookid)) {
|
||||
}
|
||||
header('Content-Type: text/vcard');
|
||||
header('Content-Disposition: inline; filename='
|
||||
. str_replace(' ', '_', $data['fullname']) . '.vcf');
|
||||
echo $data['carddata'];
|
||||
. str_replace(' ', '_', $contact->FN) . '.vcf');
|
||||
echo $data;
|
||||
} elseif(!is_null($selectedids)) {
|
||||
$selectedids = explode(',', $selectedids);
|
||||
$l10n = \OC_L10N::get('contacts');
|
||||
|
@ -104,6 +104,13 @@ abstract class PIMObjectAbstract implements IPIMObject {
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractBackend
|
||||
*/
|
||||
function getBackend() {
|
||||
return $this->backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $permission
|
||||
* @return boolean
|
||||
|
@ -76,6 +76,7 @@ class Addressbook extends PIMCollectionAbstract {
|
||||
public function getMetaData() {
|
||||
$metadata = $this->addressBookInfo;
|
||||
$metadata['lastmodified'] = $this->lastModified();
|
||||
$metadata['backend'] = $this->getBackend()->name;
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
@ -107,6 +108,10 @@ class Addressbook extends PIMCollectionAbstract {
|
||||
return $this->addressBookInfo['permissions'];
|
||||
}
|
||||
|
||||
function getBackend() {
|
||||
return $this->backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specific child node, referenced by its id
|
||||
*
|
||||
@ -164,8 +169,8 @@ class Addressbook extends PIMCollectionAbstract {
|
||||
* @param array|VObject\VCard $data
|
||||
* @return int|bool
|
||||
*/
|
||||
public function addChild($data) {
|
||||
if($data instanceof VObject\VCard || is_array($data)) {
|
||||
public function addChild($data = null) {
|
||||
//if($data instanceof VObject\VCard || is_array($data)) {
|
||||
$contact = new Contact($this, $this->backend, $data);
|
||||
if($contact->save() === false) {
|
||||
return false;
|
||||
@ -173,12 +178,12 @@ class Addressbook extends PIMCollectionAbstract {
|
||||
$id = $contact->getId();
|
||||
$this->objects[$id] = $contact;
|
||||
return $id;
|
||||
} else {
|
||||
/*} else {
|
||||
throw new Exception(
|
||||
__METHOD__
|
||||
. ' This method accepts only an array or an instance of OCA\\Contacts\\VCard'
|
||||
);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
13
lib/app.php
13
lib/app.php
@ -37,7 +37,7 @@ class App {
|
||||
protected static $addressBooks = array();
|
||||
/**
|
||||
* If backends are added to this map, they will be automatically mapped
|
||||
* to their respective classes, if constructed with the 'createBackend' method.
|
||||
* to their respective classes, if constructed with the 'getBackend' method.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@ -61,16 +61,15 @@ class App {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the new backend by name, but in addition will also see if
|
||||
* there's a class mapped to the property name.
|
||||
* Gets backend by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Backend\AbstractBackend
|
||||
*/
|
||||
static public function createBackend($name) {
|
||||
static public function getBackend($name, $user = null) {
|
||||
$name = $name ? $name : 'database';
|
||||
if (isset(self::$backendClasses[$name])) {
|
||||
return new self::$backendClasses[$name]();
|
||||
return new self::$backendClasses[$name]($user);
|
||||
} else {
|
||||
throw new \Exception('No backend for: ' . $name);
|
||||
}
|
||||
@ -88,7 +87,7 @@ class App {
|
||||
public function getAddressBooksForUser() {
|
||||
if(!self::$addressBooks) {
|
||||
foreach(array_keys(self::$backendClasses) as $backendName) {
|
||||
$backend = self::createBackend($backendName);
|
||||
$backend = self::getBackend($backendName, $this->user);
|
||||
$addressBooks = $backend->getAddressBooksForUser();
|
||||
foreach($addressBooks as $addressBook) {
|
||||
$addressBook['backend'] = $backendName;
|
||||
@ -115,7 +114,7 @@ class App {
|
||||
}
|
||||
}
|
||||
// TODO: Check for return values
|
||||
$backend = self::createBackend($backendName);
|
||||
$backend = self::getBackend($backendName, $this->user);
|
||||
$info = $backend->getAddressBook($addressbookid);
|
||||
// FIXME: Backend name should be set by the backend.
|
||||
$info['backend'] = $backendName;
|
||||
|
@ -353,15 +353,21 @@ class Database extends AbstractBackend {
|
||||
* The $id for Database and Shared backends can be an array containing
|
||||
* either 'id' or 'uri' to be able to play seamlessly with the
|
||||
* CardDAV backend.
|
||||
* FIXME: $addressbookid isn't used in the query, so there's no access control.
|
||||
* OTOH the groups backend - OC_VCategories - doesn't no about parent collections
|
||||
* only object IDs. Hmm.
|
||||
* I could make a hack and add an optional, not documented 'nostrict' argument
|
||||
* so it doesn't look for addressbookid.
|
||||
*
|
||||
* @param string $addressbookid
|
||||
* @param mixed $id Contact ID
|
||||
* @return array|false
|
||||
*/
|
||||
public function getContact($addressbookid, $id) {
|
||||
public function getContact($addressbookid, $id, $noCollection = false) {
|
||||
//\OCP\Util::writeLog('contacts', __METHOD__.' identifier: '
|
||||
// . print_r($id, true), \OCP\Util::DEBUG);
|
||||
|
||||
$ids = array($id);
|
||||
$where_query = '`id` = ?';
|
||||
if(is_array($id)) {
|
||||
$where_query = '';
|
||||
@ -376,11 +382,17 @@ class Database extends AbstractBackend {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$noCollection) {
|
||||
$where_query .= ' AND `addressbookid` = ?';
|
||||
$ids[] = $addressbookid;
|
||||
}
|
||||
|
||||
try {
|
||||
$query = 'SELECT `id`, `carddata`, `lastmodified`, `fullname` AS `displayname` FROM `'
|
||||
. $this->cardsTableName . '` WHERE ' . $where_query;
|
||||
$stmt = \OCP\DB::prepare($query);
|
||||
$result = $stmt->execute(array($id));
|
||||
$result = $stmt->execute($ids);
|
||||
if (\OC_DB::isError($result)) {
|
||||
\OC_Log::write('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
|
||||
return false;
|
||||
@ -485,7 +497,7 @@ class Database extends AbstractBackend {
|
||||
* @see getContact
|
||||
* @return bool
|
||||
*/
|
||||
public function updateContact($addressbookid, $id, $contact) {
|
||||
public function updateContact($addressbookid, $id, $contact, $noCollection = false) {
|
||||
if(!$contact instanceof Contact) {
|
||||
try {
|
||||
$contact = Reader::read($contact);
|
||||
@ -512,17 +524,25 @@ class Database extends AbstractBackend {
|
||||
} else {
|
||||
$qname = 'createcontactbyid';
|
||||
}
|
||||
|
||||
$now = new \DateTime;
|
||||
$contact->REV = $now->format(\DateTime::W3C);
|
||||
|
||||
$data = $contact->serialize();
|
||||
|
||||
$updates = array($contact->FN, $data, time(), $id);
|
||||
if(!$noCollection) {
|
||||
$where_query .= ' AND `addressbookid` = ?';
|
||||
$updates[] = $addressbookid;
|
||||
}
|
||||
|
||||
$query = 'UPDATE `' . $this->cardsTableName
|
||||
. '` SET `fullname` = ?,`carddata` = ?, `lastmodified` = ? WHERE ' . $where_query;
|
||||
if(!isset(self::$preparedQueries[$qname])) {
|
||||
self::$preparedQueries[$qname] = \OCP\DB::prepare($query);
|
||||
}
|
||||
try {
|
||||
$result = self::$preparedQueries[$qname]->execute(array($contact->FN, $data, time(), $id));
|
||||
$result = self::$preparedQueries[$qname]->execute($updates);
|
||||
if (\OC_DB::isError($result)) {
|
||||
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
|
||||
return false;
|
||||
|
226
lib/contact.php
226
lib/contact.php
@ -54,11 +54,14 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
//\OCP\Util::writeLog('contacts', __METHOD__, \OCP\Util::DEBUG);
|
||||
$this->props['parent'] = $parent;
|
||||
$this->props['backend'] = $backend;
|
||||
$this->props['retrieved'] = false;
|
||||
$this->props['saved'] = false;
|
||||
|
||||
if(!is_null($data)) {
|
||||
if($data instanceof VObject\VCard) {
|
||||
foreach($obj->children as $child) {
|
||||
$this->add($child);
|
||||
$this->setRetrieved(true);
|
||||
}
|
||||
} elseif(is_array($data)) {
|
||||
foreach($data as $key => $value) {
|
||||
@ -83,15 +86,15 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
case 'displayname':
|
||||
case 'fullname':
|
||||
$this->props['displayname'] = $value;
|
||||
//$this->FN = $value;
|
||||
$this->FN = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}/* else {
|
||||
throw new Exception(
|
||||
__METHOD__ . ' 3rd argument must either be an array or a subclass of \VObject\VCard'
|
||||
);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +115,7 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
'lastmodified' => $this->lastModified(),
|
||||
'owner' => $this->getOwner(),
|
||||
'parent' => $this->getParent()->getId(),
|
||||
'backend' => $this->getBackend()->name,
|
||||
);
|
||||
}
|
||||
|
||||
@ -215,21 +219,34 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function save() {
|
||||
public function save($force = false) {
|
||||
if($this->isSaved() && !$force) {
|
||||
\OCP\Util::writeLog('contacts', __METHOD__.' Already saved: ' . print_r($this->props, true), \OCP\Util::DEBUG);
|
||||
return true;
|
||||
}
|
||||
if(isset($this->FN)) {
|
||||
$this->props['displayname'] = (string)$this->FN;
|
||||
}
|
||||
if($this->getId()) {
|
||||
return $this->props['backend']->updateContact(
|
||||
$this->getParent()->getId(),
|
||||
$this->getId(),
|
||||
$this->serialize()
|
||||
);
|
||||
if($this->props['backend']
|
||||
->updateContact(
|
||||
$this->getParent()->getId(),
|
||||
$this->getId(),
|
||||
$this->serialize()
|
||||
)
|
||||
) {
|
||||
$this->props['lastmodified'] = time();
|
||||
$this->setSaved(true);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
//print(__METHOD__.' ' . print_r($this->getParent(), true));
|
||||
$this->props['id'] = $this->props['backend']->createContact(
|
||||
$this->getParent()->getId(), $this
|
||||
);
|
||||
$this->setSaved(true);
|
||||
return $this->getId() !== false;
|
||||
}
|
||||
}
|
||||
@ -241,7 +258,7 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
public function retrieve() {
|
||||
//error_log(__METHOD__);
|
||||
//\OCP\Util::writeLog('contacts', __METHOD__.' ' . print_r($this->props, true), \OCP\Util::DEBUG);
|
||||
if($this->children) {
|
||||
if($this->isRetrieved()) {
|
||||
//\OCP\Util::writeLog('contacts', __METHOD__. ' children', \OCP\Util::DEBUG);
|
||||
return true;
|
||||
} else {
|
||||
@ -255,12 +272,13 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
= strtr($child->value, array('\,' => ',', '\;' => ';', '\\\\' => '\\'));
|
||||
}
|
||||
}
|
||||
$this->setRetrieved(true);
|
||||
//$this->children = $this->props['vcard']->children();
|
||||
unset($this->props['vcard']);
|
||||
return true;
|
||||
} elseif(!isset($this->props['carddata'])) {
|
||||
$result = $this->props['backend']->getContact(
|
||||
$this->parent->getId(),
|
||||
$this->getParent()->getId(),
|
||||
$this->id
|
||||
);
|
||||
if($result) {
|
||||
@ -269,6 +287,7 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
foreach($result['vcard']->children() as $child) {
|
||||
$this->add($child);
|
||||
}
|
||||
$this->setRetrieved(true);
|
||||
return true;
|
||||
} elseif(isset($result['carddata'])) {
|
||||
// Save internal values
|
||||
@ -294,13 +313,14 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
foreach($obj->children as $child) {
|
||||
$this->add($child);
|
||||
}
|
||||
$this->setRetrieved(true);
|
||||
} else {
|
||||
\OCP\Util::writeLog('contacts', __METHOD__.' Error reading: ' . print_r($data, true), \OCP\Util::DEBUG);
|
||||
return false;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\OCP\Util::writeLog('contacts', __METHOD__ .
|
||||
' Error parsing carddata: ' . $e->getMessage(),
|
||||
' Error parsing carddata for: ' . $this->getId() . ' ' . $e->getMessage(),
|
||||
\OCP\Util::ERROR);
|
||||
return false;
|
||||
}
|
||||
@ -309,20 +329,161 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a property by the checksum of its serialized value
|
||||
* Get a property by the checksum of its serialized value
|
||||
*
|
||||
* @param string $checksum An 8 char m5d checksum.
|
||||
* @return bool
|
||||
* @return \Sabre\VObject\Property Property by reference
|
||||
* @throws An exception with error code 404 if the property is not found.
|
||||
*/
|
||||
public function unsetPropertyByChecksum($checksum) {
|
||||
public function getPropertyByChecksum($checksum) {
|
||||
$this->retrieve();
|
||||
foreach($this->children as $i => $property) {
|
||||
foreach($this->children as $i => &$property) {
|
||||
if(substr(md5($property->serialize()), 0, 8) == $checksum ) {
|
||||
unset($this->children[$i]);
|
||||
return true;
|
||||
return $property;
|
||||
}
|
||||
}
|
||||
throw new Exception('Property not found', 404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a property by the checksum of its serialized value
|
||||
* It is up to the caller to call ->save()
|
||||
*
|
||||
* @param string $checksum An 8 char m5d checksum.
|
||||
* @throws @see getPropertyByChecksum
|
||||
*/
|
||||
public function unsetPropertyByChecksum($checksum) {
|
||||
$property = $this->getPropertyByChecksum($checksum);
|
||||
unset($property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a property by the checksum of its serialized value
|
||||
* It is up to the caller to call ->save()
|
||||
*
|
||||
* @param string $checksum An 8 char m5d checksum.
|
||||
* @param string $name Property name
|
||||
* @param mixed $value
|
||||
* @param array $parameters
|
||||
* @throws @see getPropertyByChecksum
|
||||
* @return string new checksum
|
||||
*/
|
||||
public function setPropertyByChecksum($checksum, $name, $value, $parameters=array()) {
|
||||
$property = $this->getPropertyByChecksum($checksum);
|
||||
switch($name) {
|
||||
case 'EMAIL':
|
||||
$value = strtolower($value);
|
||||
$property->setValue($value);
|
||||
break;
|
||||
case 'ADR':
|
||||
if(is_array($value)) {
|
||||
$property->setParts($value);
|
||||
} else {
|
||||
debug('Saving N ' . $value);
|
||||
$property->setValue($value);
|
||||
}
|
||||
break;
|
||||
case 'IMPP':
|
||||
if(is_null($parameters) || !isset($parameters['X-SERVICE-TYPE'])) {
|
||||
bailOut(App::$l10n->t('Missing IM parameter.'));
|
||||
}
|
||||
$impp = Utils\Properties::getIMOptions($parameters['X-SERVICE-TYPE']);
|
||||
if(is_null($impp)) {
|
||||
bailOut(App::$l10n->t('Unknown IM: '.$parameters['X-SERVICE-TYPE']));
|
||||
}
|
||||
$value = $impp['protocol'] . ':' . $value;
|
||||
$property->setValue($value);
|
||||
break;
|
||||
default:
|
||||
$property->setValue($value);
|
||||
break;
|
||||
}
|
||||
$this->setParameters($property, $parameters);
|
||||
return substr(md5($property->serialize()), 0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a property by the property name.
|
||||
* It is up to the caller to call ->save()
|
||||
*
|
||||
* @param string $name Property name
|
||||
* @param mixed $value
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
public function setPropertyByName($name, $value, $parameters=array()) {
|
||||
// TODO: parameters are ignored for now.
|
||||
switch($name) {
|
||||
case 'BDAY':
|
||||
try {
|
||||
$date = New \DateTime($value);
|
||||
} catch(\Exception $e) {
|
||||
\OCP\Util::writeLog('contacts',
|
||||
__METHOD__.' DateTime exception: ' . $e->getMessage(),
|
||||
\OCP\Util::ERROR
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$value = $date->format('Y-m-d');
|
||||
$this->BDAY = $value;
|
||||
$this->BDAY->VALUE = 'DATE';
|
||||
break;
|
||||
case 'N':
|
||||
$property = $this->select($name);
|
||||
if(count($property) === 0) {
|
||||
$property = VObject\Property::create($name);
|
||||
$this->add($property);
|
||||
} else {
|
||||
// Actually no idea why this works
|
||||
$property = array_shift($property);
|
||||
}
|
||||
if(is_array($value)) {
|
||||
$property->setParts($value);
|
||||
} else {
|
||||
$this->N = $value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->{$name} = $value;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function setParameters($property, $parameters, $reset = false) {
|
||||
if(!$parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($reset) {
|
||||
$property->parameters = array();
|
||||
}
|
||||
debug('Setting parameters: ' . print_r($parameters, true));
|
||||
foreach($parameters as $key => $parameter) {
|
||||
debug('Adding parameter: ' . $key);
|
||||
if(is_array($parameter)) {
|
||||
foreach($parameter as $val) {
|
||||
if(is_array($val)) {
|
||||
foreach($val as $val2) {
|
||||
if(trim($key) && trim($val2)) {
|
||||
debug('Adding parameter: '.$key.'=>'.print_r($val2, true));
|
||||
$property->add($key, strip_tags($val2));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(trim($key) && trim($val)) {
|
||||
debug('Adding parameter: '.$key.'=>'.print_r($val, true));
|
||||
$property->add($key, strip_tags($val));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(trim($key) && trim($parameter)) {
|
||||
debug('Adding parameter: '.$key.'=>'.print_r($parameter, true));
|
||||
$property->add($key, strip_tags($parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function lastModified() {
|
||||
@ -368,4 +529,31 @@ class Contact extends VObject\VCard implements IPIMObject {
|
||||
\OCP\Util::writeLog('contacts', 'Caching ' . $key, \OCP\Util::DEBUG);
|
||||
return \OC_Cache::get(self::THUMBNAIL_PREFIX . $key);
|
||||
}
|
||||
|
||||
public function __set($key, $value) {
|
||||
parent::__set($key, $value);
|
||||
$this->setSaved(false);
|
||||
}
|
||||
|
||||
public function __unset($id) {
|
||||
parent::__unset($key, $value);
|
||||
$this->setSaved(false);
|
||||
}
|
||||
|
||||
protected function setRetrieved($state) {
|
||||
$this->props['retrieved'] = $state;
|
||||
}
|
||||
|
||||
protected function isRetrieved() {
|
||||
return $this->props['retrieved'];
|
||||
}
|
||||
|
||||
protected function setSaved($state) {
|
||||
$this->props['saved'] = $state;
|
||||
}
|
||||
|
||||
protected function isSaved() {
|
||||
return $this->props['saved'];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -98,6 +98,11 @@ interface IPIMObject {
|
||||
*/
|
||||
function getPermissions();
|
||||
|
||||
/**
|
||||
* @return AbstractBackend
|
||||
*/
|
||||
function getBackend();
|
||||
|
||||
/**
|
||||
* @param integer $permission
|
||||
* @return boolean
|
||||
|
@ -30,6 +30,8 @@ use OCA\Contacts\Contact;
|
||||
* This class serializes properties, components an
|
||||
* arrays of components into a format suitable for
|
||||
* passing to a JSON response.
|
||||
* TODO: Return jCard (almost) compliant data, but still omitting unneeded data.
|
||||
* http://tools.ietf.org/html/draft-kewisch-vcard-in-json-01
|
||||
*/
|
||||
|
||||
class JSONSerializer {
|
||||
|
Loading…
Reference in New Issue
Block a user