1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2024-12-04 15:24:35 +01:00
OwncloudContactsOfficial/lib/contact.php

850 lines
23 KiB
PHP
Raw Normal View History

<?php
/**
* ownCloud - Contact object
*
* @author Thomas Tanghus
2014-01-26 00:40:22 +01:00
* @copyright 2012-2014 Thomas Tanghus (thomas@tanghus.net)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Contacts;
use Sabre\VObject\Property,
OCA\Contacts\Utils\Properties;
2013-03-29 16:44:14 +01:00
/**
* Subclass this class or implement IPIMObject interface for PIM objects
*/
class Contact extends VObject\VCard implements IPIMObject {
/**
* The name of the object type in this case VCARD.
*
* This is used when serializing the object.
*
* @var string
*/
public $name = 'VCARD';
/**
* @brief language object
*
* @var OC_L10N
*/
public static $l10n;
protected $props = array();
2013-03-17 21:32:53 +01:00
/**
* Create a new Contact object
*
* @param AddressBook $parent
2014-03-08 19:09:17 +01:00
* @param Backend\AbstractBackend $backend
2013-03-17 21:32:53 +01:00
* @param mixed $data
*/
public function __construct($parent, $backend, $data = null) {
parent::__construct('VCARD');
self::$l10n = $parent::$l10n;
2014-03-18 23:51:32 +01:00
//\OCP\Util::writeLog('contacts', __METHOD__ . ' , data: ' . print_r($data, true), \OCP\Util::DEBUG);
$this->props['parent'] = $parent;
$this->props['backend'] = $backend;
2013-03-25 17:10:21 +01:00
$this->props['retrieved'] = false;
$this->props['saved'] = false;
2013-03-12 09:15:40 +01:00
2014-04-24 18:32:33 +02:00
if (!is_null($data)) {
if ($data instanceof VObject\VCard) {
foreach ($data->children as $child) {
2013-03-17 21:32:53 +01:00
$this->add($child);
}
2013-05-06 01:50:03 +02:00
$this->setRetrieved(true);
2014-04-24 18:32:33 +02:00
} elseif (is_array($data)) {
foreach ($data as $key => $value) {
switch ($key) {
2013-03-17 21:32:53 +01:00
case 'id':
$this->props['id'] = $value;
break;
case 'permissions':
$this->props['permissions'] = $value;
break;
2013-03-17 21:32:53 +01:00
case 'lastmodified':
$this->props['lastmodified'] = $value;
break;
case 'uri':
$this->props['uri'] = $value;
break;
case 'carddata':
$this->props['carddata'] = $value;
2013-03-20 11:26:01 +01:00
$this->retrieve();
2013-03-17 21:32:53 +01:00
break;
case 'vcard':
$this->props['vcard'] = $value;
$this->retrieve();
break;
case 'displayname':
case 'fullname':
2013-12-19 23:28:24 +01:00
if(is_string($value)) {
$this->props['displayname'] = $value;
$this->FN = $value;
// Set it to saved again as we're not actually changing anything
$this->setSaved();
}
2013-03-17 21:32:53 +01:00
break;
}
2013-03-12 09:15:40 +01:00
}
}
2013-03-12 09:15:40 +01:00
}
}
2013-03-16 15:59:23 +01:00
/**
* @return array|null
*/
public function getMetaData() {
2014-04-24 18:32:33 +02:00
if (!$this->hasPermission(\OCP\PERMISSION_READ)) {
2013-05-18 16:49:02 +02:00
throw new \Exception(self::$l10n->t('You do not have permissions to see this contact'), 403);
}
2014-04-24 18:32:33 +02:00
if (!isset($this->props['displayname'])) {
if (!$this->retrieve()) {
2013-03-16 15:59:23 +01:00
\OCP\Util::writeLog('contacts', __METHOD__.' error reading: '.print_r($this->props, true), \OCP\Util::ERROR);
return null;
}
}
return array(
'id' => $this->getId(),
'displayname' => $this->getDisplayName(),
'permissions' => $this->getPermissions(),
'lastmodified' => $this->lastModified(),
'owner' => $this->getOwner(),
'parent' => $this->getParent()->getId(),
2013-03-25 17:10:21 +01:00
'backend' => $this->getBackend()->name,
2013-03-16 15:59:23 +01:00
);
}
/**
* Get a unique key combined of backend name, address book id and contact id.
*
* @return string
*/
public function combinedKey() {
return $this->getBackend()->name . '::' . $this->getParent()->getId() . '::' . $this->getId();
}
/**
* @return string|null
*/
public function getOwner() {
2014-04-24 18:32:33 +02:00
return isset($this->props['owner'])
? $this->props['owner']
: $this->getParent()->getOwner();
}
/**
* @return string|null
*/
public function getId() {
2013-03-12 09:15:40 +01:00
return isset($this->props['id']) ? $this->props['id'] : null;
}
/**
* @return string|null
*/
2014-03-23 19:02:16 +01:00
public function getDisplayName() {
2014-04-24 18:32:33 +02:00
if (!$this->hasPermission(\OCP\PERMISSION_READ)) {
2013-05-18 16:49:02 +02:00
throw new \Exception(self::$l10n->t('You do not have permissions to see this contact'), 403);
}
return isset($this->props['displayname'])
? $this->props['displayname']
: (isset($this->FN) ? $this->FN : null);
2013-03-12 09:15:40 +01:00
}
/**
* @return string|null
*/
public function getURI() {
return isset($this->props['uri']) ? $this->props['uri'] : null;
}
2013-05-09 05:56:32 +02:00
/**
* @return string|null
* TODO: Cache result.
*/
public function getETag() {
$this->retrieve();
return md5($this->serialize());
}
/**
* If this object is part of a collection return a reference
* to the parent object, otherwise return null.
* @return IPIMObject|null
*/
2013-05-30 20:52:12 +02:00
public function getParent() {
return $this->props['parent'];
}
2013-05-30 20:52:12 +02:00
public function getBackend() {
return $this->props['backend'];
}
/** CRUDS permissions (Create, Read, Update, Delete, Share)
*
* @return integer
*/
2013-05-30 20:52:12 +02:00
public function getPermissions() {
return isset($this->props['permissions'])
? $this->props['permissions']
2014-04-24 18:32:33 +02:00
: $this->getParent()->getPermissions();
}
/**
* @param integer $permission
* @return bool
*/
2013-05-30 20:52:12 +02:00
public function hasPermission($permission) {
return $this->getPermissions() & $permission;
}
2013-03-12 20:00:22 +01:00
/**
* Save the address book data to backend
* FIXME
*
* @param array $data
* @return bool
*/
/* public function update(array $data) {
2013-03-12 20:00:22 +01:00
foreach($data as $key => $value) {
switch($key) {
case 'displayname':
$this->addressBookInfo['displayname'] = $value;
break;
case 'description':
$this->addressBookInfo['description'] = $value;
break;
}
}
return $this->props['backend']->updateContact(
$this->getParent()->getId(),
$this->getId(),
$this
);
}
*/
2013-03-12 20:00:22 +01:00
/**
* Delete the data from backend
*
* FIXME: Should be removed as it could leave the parent with a dataless object.
*
2013-03-12 20:00:22 +01:00
* @return bool
*/
public function delete() {
2014-04-24 18:32:33 +02:00
if (!$this->hasPermission(\OCP\PERMISSION_DELETE)) {
2013-05-18 16:49:02 +02:00
throw new \Exception(self::$l10n->t('You do not have permissions to delete this contact'), 403);
}
2013-03-12 20:00:22 +01:00
return $this->props['backend']->deleteContact(
$this->getParent()->getId(),
$this->getId()
);
}
/**
* Save the contact data to backend
*
* @return bool
*/
2013-03-25 17:10:21 +01:00
public function save($force = false) {
2014-04-24 18:32:33 +02:00
if (!$this->hasPermission(\OCP\PERMISSION_UPDATE)) {
2013-05-18 16:49:02 +02:00
throw new \Exception(self::$l10n->t('You do not have permissions to update this contact'), 403);
}
2014-04-24 18:32:33 +02:00
if ($this->isSaved() && !$force) {
2013-03-25 17:10:21 +01:00
\OCP\Util::writeLog('contacts', __METHOD__.' Already saved: ' . print_r($this->props, true), \OCP\Util::DEBUG);
return true;
}
2014-03-18 23:51:32 +01:00
2014-04-24 18:32:33 +02:00
if (isset($this->FN)) {
2013-03-20 11:26:01 +01:00
$this->props['displayname'] = (string)$this->FN;
}
2014-03-18 23:51:32 +01:00
2014-04-24 18:32:33 +02:00
if ($this->getId()) {
if (!$this->getBackend()->hasContactMethodFor(\OCP\PERMISSION_UPDATE)) {
2013-05-18 16:49:02 +02:00
throw new \Exception(self::$l10n->t('The backend for this contact does not support updating it'), 501);
}
2014-04-24 18:32:33 +02:00
if ($this->getBackend()
2013-03-25 17:10:21 +01:00
->updateContact(
$this->getParent()->getId(),
$this->getId(),
$this
2013-03-25 17:10:21 +01:00
)
) {
$this->props['lastmodified'] = time();
$this->setSaved(true);
return true;
} else {
return false;
}
} else {
2014-04-24 18:32:33 +02:00
if (!$this->getBackend()->hasContactMethodFor(\OCP\PERMISSION_CREATE)) {
2014-05-25 13:18:20 +02:00
throw new \Exception(self::$l10n->t('This backend does not support adding contacts'), 501);
}
$this->props['id'] = $this->getBackend()->createContact(
2013-03-20 11:26:01 +01:00
$this->getParent()->getId(), $this
);
2013-03-25 17:10:21 +01:00
$this->setSaved(true);
2013-03-17 21:32:53 +01:00
return $this->getId() !== false;
}
}
2013-03-16 15:59:23 +01:00
/**
* Get the data from the backend
2013-03-20 11:26:01 +01:00
* FIXME: Clean this up and make sure the logic is OK.
2014-03-18 15:16:03 +01:00
*
* @return bool
2013-03-16 15:59:23 +01:00
*/
public function retrieve() {
if ($this->isRetrieved()) {
//\OCP\Util::writeLog('contacts', __METHOD__. ' children', \OCP\Util::DEBUG);
return true;
} else {
2013-03-20 11:26:01 +01:00
$data = null;
2013-03-12 20:00:22 +01:00
if(isset($this->props['vcard'])
&& $this->props['vcard'] instanceof VObject\VCard) {
2013-03-16 15:59:23 +01:00
foreach($this->props['vcard']->children() as $child) {
$this->add($child);
2013-03-20 11:26:01 +01:00
if($child->name === 'FN') {
$this->props['displayname']
= strtr($child->getValue(), array('\,' => ',', '\;' => ';', '\\\\' => '\\'));
2013-03-20 11:26:01 +01:00
}
2013-03-16 15:59:23 +01:00
}
2013-03-25 17:10:21 +01:00
$this->setRetrieved(true);
$this->setSaved(true);
2013-03-16 15:59:23 +01:00
//$this->children = $this->props['vcard']->children();
2013-03-12 20:00:22 +01:00
unset($this->props['vcard']);
return true;
2014-04-24 18:32:33 +02:00
} elseif (!isset($this->props['carddata'])) {
2013-03-12 20:00:22 +01:00
$result = $this->props['backend']->getContact(
2013-03-25 17:10:21 +01:00
$this->getParent()->getId(),
2013-09-24 13:39:45 +02:00
$this->getId()
2013-03-12 20:00:22 +01:00
);
2014-04-24 18:32:33 +02:00
if ($result) {
if (isset($result['vcard'])
2013-03-12 20:00:22 +01:00
&& $result['vcard'] instanceof VObject\VCard) {
2014-04-24 18:32:33 +02:00
foreach ($result['vcard']->children() as $child) {
2013-03-16 15:59:23 +01:00
$this->add($child);
}
2013-03-25 17:10:21 +01:00
$this->setRetrieved(true);
return true;
2014-04-24 18:32:33 +02:00
} elseif (isset($result['carddata'])) {
// Save internal values
$data = $result['carddata'];
$this->props['carddata'] = $result['carddata'];
$this->props['lastmodified'] = isset($result['lastmodified'])
? $result['lastmodified']
: null;
2013-03-20 11:26:01 +01:00
$this->props['displayname'] = $result['displayname'];
$this->props['permissions'] = $result['permissions'];
} else {
\OCP\Util::writeLog('contacts', __METHOD__
. ' Could not get vcard or carddata: '
. $this->getId()
. print_r($result, true), \OCP\Util::DEBUG);
return false;
}
} else {
\OCP\Util::writeLog('contacts', __METHOD__.' Error getting contact: ' . $this->getId(), \OCP\Util::DEBUG);
}
2014-04-24 18:32:33 +02:00
} elseif (isset($this->props['carddata'])) {
2013-03-16 15:59:23 +01:00
$data = $this->props['carddata'];
}
try {
$obj = \Sabre\VObject\Reader::read(
$data,
2013-03-12 09:15:40 +01:00
\Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES
);
2014-04-24 18:32:33 +02:00
if ($obj) {
foreach ($obj->children as $child) {
if($child->name === 'VERSION' || $child->name === 'PRODID') {
parent::__set($child->name, $child);
} else {
$this->add($child);
}
2013-03-16 15:59:23 +01:00
}
2013-03-25 17:10:21 +01:00
$this->setRetrieved(true);
$this->setSaved(true);
2013-03-16 15:59:23 +01:00
} else {
\OCP\Util::writeLog('contacts', __METHOD__.' Error reading: ' . print_r($data, true), \OCP\Util::DEBUG);
2013-03-16 15:59:23 +01:00
return false;
}
} catch (\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__ .
2013-03-25 17:10:21 +01:00
' Error parsing carddata for: ' . $this->getId() . ' ' . $e->getMessage(),
\OCP\Util::ERROR);
return false;
}
}
return true;
}
/**
* Get the PHOTO or LOGO
*
* @return \OCP\Image|null
*/
public function getPhoto() {
$image = new \OCP\Image();
if (isset($this->PHOTO) && $image->loadFromBase64((string)$this->PHOTO)) {
return $image;
} elseif (isset($this->LOGO) && $image->loadFromBase64((string)$this->LOGO)) {
return $image;
}
}
2014-03-20 21:53:13 +01:00
/**
* Set the contact photo.
*
* @param \OCP\Image $photo
*/
public function setPhoto(\OCP\Image $photo) {
// For vCard 3.0 the type must be e.g. JPEG or PNG
// For version 4.0 the full mimetype should be used.
// https://tools.ietf.org/html/rfc2426#section-3.1.4
2014-04-24 18:32:33 +02:00
if (strval($this->VERSION) === '4.0') {
2014-03-20 21:53:13 +01:00
$type = $photo->mimeType();
} else {
$type = explode('/', $photo->mimeType());
$type = strtoupper(array_pop($type));
}
2014-04-24 18:32:33 +02:00
if (isset($this->PHOTO)) {
2014-03-20 21:53:13 +01:00
$property = $this->PHOTO;
2014-04-24 18:32:33 +02:00
if (!$property) {
2014-03-20 21:53:13 +01:00
return false;
}
$property->setValue(strval($photo));
$property->parameters = array();
$property->parameters[]
= new \Sabre\VObject\Parameter('ENCODING', 'b');
$property->parameters[]
= new \Sabre\VObject\Parameter('TYPE', $photo->mimeType());
$this->PHOTO = $property;
} else {
$this->add('PHOTO',
strval($photo), array('ENCODING' => 'b',
'TYPE' => $type));
// TODO: Fix this hack
$this->setSaved(false);
}
return true;
}
2013-03-26 12:35:37 +01:00
/**
* Get a property index in the contact by the checksum of its serialized value
*
* @param string $checksum An 8 char m5d checksum.
* @return \Sabre\VObject\Property Property by reference
* @throws An exception with error code 404 if the property is not found.
*/
public function getPropertyIndexByChecksum($checksum) {
$this->retrieve();
$idx = 0;
2014-04-24 18:32:33 +02:00
foreach ($this->children as $i => &$property) {
if (substr(md5($property->serialize()), 0, 8) == $checksum ) {
2013-03-26 12:35:37 +01:00
return $idx;
}
$idx += 1;
}
2013-05-22 03:18:55 +02:00
throw new \Exception(self::$l10n->t('Property not found'), 404);
2013-03-26 12:35:37 +01:00
}
/**
2013-03-25 17:10:21 +01:00
* Get a property by the checksum of its serialized value
*
* @param string $checksum An 8 char m5d checksum.
2013-03-25 17:10:21 +01:00
* @return \Sabre\VObject\Property Property by reference
* @throws An exception with error code 404 if the property is not found.
*/
2013-03-25 17:10:21 +01:00
public function getPropertyByChecksum($checksum) {
2013-03-16 15:59:23 +01:00
$this->retrieve();
2014-04-24 18:32:33 +02:00
foreach ($this->children as $i => &$property) {
if (substr(md5($property->serialize()), 0, 8) == $checksum ) {
2013-03-25 17:10:21 +01:00
return $property;
}
}
2013-05-18 16:49:02 +02:00
throw new \Exception(self::$l10n->t('Property not found'), 404);
2013-03-25 17:10:21 +01:00
}
/**
* 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) {
2013-03-26 12:35:37 +01:00
$idx = $this->getPropertyIndexByChecksum($checksum);
unset($this->children[$idx]);
$this->setSaved(false);
2013-03-25 17:10:21 +01:00
}
/**
* 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()) {
2014-04-24 18:32:33 +02:00
if ($checksum === 'new') {
$property = $this->createProperty($name);
$this->add($property);
} else {
$property = $this->getPropertyByChecksum($checksum);
}
2014-04-24 18:32:33 +02:00
switch ($name) {
2013-03-25 17:10:21 +01:00
case 'EMAIL':
$value = strtolower($value);
$property->setValue($value);
break;
case 'ADR':
if(is_array($value)) {
$property->setParts($value);
} else {
$property->setValue($value);
}
break;
case 'IMPP':
2014-04-24 18:32:33 +02:00
if (is_null($parameters) || !isset($parameters['X-SERVICE-TYPE'])) {
2013-05-18 16:49:02 +02:00
throw new \InvalidArgumentException(self::$l10n->t(' Missing IM parameter for: ') . $name. ' ' . $value, 412);
2013-03-25 17:10:21 +01:00
}
$serviceType = $parameters['X-SERVICE-TYPE'];
2014-04-24 18:32:33 +02:00
if (is_array($serviceType)) {
$serviceType = $serviceType[0];
}
$impp = Utils\Properties::getIMOptions($serviceType);
2014-04-24 18:32:33 +02:00
if (is_null($impp)) {
2013-05-18 16:49:02 +02:00
throw new \UnexpectedValueException(self::$l10n->t('Unknown IM: ') . $serviceType, 415);
2013-03-25 17:10:21 +01:00
}
$value = $impp['protocol'] . ':' . $value;
$property->setValue($value);
break;
default:
2013-04-03 16:55:56 +02:00
\OCP\Util::writeLog('contacts', __METHOD__.' adding: '.$name. ' ' . $value, \OCP\Util::DEBUG);
2013-03-25 17:10:21 +01:00
$property->setValue($value);
break;
}
$this->setParameters($property, $parameters, true);
2013-03-26 12:35:37 +01:00
$this->setSaved(false);
2013-03-25 17:10:21 +01:00
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.
2014-04-24 18:32:33 +02:00
switch ($name) {
2013-03-25 17:10:21 +01:00
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;
2013-03-30 07:29:39 +01:00
$this->BDAY->add('VALUE', 'DATE');
//\OCP\Util::writeLog('contacts', __METHOD__.' BDAY: '.$this->BDAY->serialize(), \OCP\Util::DEBUG);
2013-03-25 17:10:21 +01:00
break;
2013-04-03 16:43:18 +02:00
case 'CATEGORIES':
2013-03-25 17:10:21 +01:00
case 'N':
2013-04-03 16:43:18 +02:00
case 'ORG':
2013-03-25 17:10:21 +01:00
$property = $this->select($name);
2014-04-24 18:32:33 +02:00
if (count($property) === 0) {
$property = $this->createProperty($name);
2013-03-25 17:10:21 +01:00
$this->add($property);
} else {
// Actually no idea why this works
$property = array_shift($property);
}
2014-04-24 18:32:33 +02:00
if (is_array($value)) {
2013-03-25 17:10:21 +01:00
$property->setParts($value);
} else {
2013-04-03 16:43:18 +02:00
$this->{$name} = $value;
2013-03-25 17:10:21 +01:00
}
break;
default:
2013-04-03 16:43:18 +02:00
\OCP\Util::writeLog('contacts', __METHOD__.' adding: '.$name. ' ' . $value, \OCP\Util::DEBUG);
2013-03-25 17:10:21 +01:00
$this->{$name} = $value;
break;
}
2013-03-26 12:35:37 +01:00
$this->setSaved(false);
2013-03-25 17:10:21 +01:00
return true;
}
protected function setParameters($property, $parameters, $reset = false) {
2014-04-24 18:32:33 +02:00
if (!$parameters) {
2013-03-25 17:10:21 +01:00
return;
}
2014-04-24 18:32:33 +02:00
if ($reset) {
2013-03-25 17:10:21 +01:00
$property->parameters = array();
}
//debug('Setting parameters: ' . print_r($parameters, true));
2014-04-24 18:32:33 +02:00
foreach ($parameters as $key => $parameter) {
//debug('Adding parameter: ' . $key);
2014-04-24 18:32:33 +02:00
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));
2013-03-25 17:10:21 +01:00
$property->add($key, strip_tags($val2));
}
}
} else {
2014-04-24 18:32:33 +02:00
if (trim($key) && trim($val)) {
//debug('Adding parameter: '.$key.'=>'.print_r($val, true));
2013-03-25 17:10:21 +01:00
$property->add($key, strip_tags($val));
}
}
}
} else {
2014-04-24 18:32:33 +02:00
if (trim($key) && trim($parameter)) {
//debug('Adding parameter: '.$key.'=>'.print_r($parameter, true));
2013-03-25 17:10:21 +01:00
$property->add($key, strip_tags($parameter));
}
}
}
}
public function lastModified() {
2014-04-24 18:32:33 +02:00
if (!isset($this->props['lastmodified']) && !$this->isRetrieved()) {
2013-03-16 15:59:23 +01:00
$this->retrieve();
}
return isset($this->props['lastmodified'])
2013-03-16 15:59:23 +01:00
? $this->props['lastmodified']
: null;
}
/**
* Merge in data from a multi-dimentional array
*
* NOTE: The data has actually already been merged client side!
* NOTE: The only properties coming from the web client are the ones
2014-03-18 00:58:01 +01:00
* defined in \OCA\Contacts\Utils\Properties::$indexProperties and
* UID is skipped for obvious reasons, and PHOTO is currently not updated.
* The data array has this structure:
*
* array(
* 'EMAIL' => array(array('value' => 'johndoe@example.com', 'parameters' = array('TYPE' => array('HOME','VOICE'))))
* );
* @param array $data
* @return bool
*/
2013-04-03 16:43:18 +02:00
public function mergeFromArray(array $data) {
2014-04-24 18:32:33 +02:00
foreach ($data as $name => $properties) {
if (in_array($name, array('PHOTO', 'UID'))) {
continue;
}
2014-04-24 18:32:33 +02:00
if (!is_array($properties)) {
2013-04-03 16:43:18 +02:00
\OCP\Util::writeLog('contacts', __METHOD__.' not an array?: ' .$name. ' '.print_r($properties, true), \OCP\Util::DEBUG);
}
2014-04-24 18:32:33 +02:00
if (in_array($name, Utils\Properties::$multiProperties)) {
2013-04-03 16:43:18 +02:00
unset($this->{$name});
}
2014-04-24 18:32:33 +02:00
foreach ($properties as $parray) {
2013-04-03 16:43:18 +02:00
\OCP\Util::writeLog('contacts', __METHOD__.' adding: ' .$name. ' '.print_r($parray['value'], true) . ' ' . print_r($parray['parameters'], true), \OCP\Util::DEBUG);
2014-04-24 18:32:33 +02:00
if (in_array($name, Utils\Properties::$multiProperties)) {
2013-04-03 16:43:18 +02:00
// TODO: wrap in try/catch, check return value
$this->setPropertyByChecksum('new', $name, $parray['value'], $parray['parameters']);
} else {
// TODO: Check return value
2014-04-24 18:32:33 +02:00
if (!isset($this->{$name})) {
2013-04-03 16:43:18 +02:00
$this->setPropertyByName($name, $parray['value'], $parray['parameters']);
}
}
}
}
$this->setSaved(false);
2013-04-03 16:43:18 +02:00
return true;
}
/**
* Merge in data from another VCard
* Used on import if a matching UID is found. Returns true if any updates
* take place, otherwise false.
*
* @param VCard $vcard
* @return bool
*/
public function mergeFromVCard(VCard $vcard) {
$updated = false;
2014-04-24 18:32:33 +02:00
foreach ($vcard->children as $property) {
if (in_array($property->name, array('REV', 'UID'))) {
continue;
}
\OCP\Util::writeLog('contacts', __METHOD__.' merging: ' .$property->name, \OCP\Util::DEBUG);
2014-04-24 18:32:33 +02:00
if (in_array($property->name, Utils\Properties::$multiProperties)) {
$ownproperties = $this->select($property->name);
2014-04-24 18:32:33 +02:00
if (count($ownproperties) === 0) {
// We don't have any instances of this property, so just add it.
$this->add($property);
$updated = true;
continue;
} else {
2014-04-24 18:32:33 +02:00
foreach ($ownproperties as $ownproperty) {
if (strtolower($property->getValue()) === strtolower($ownproperty->getValue())) {
// We already have this property, so skip both loops
continue 2;
}
}
$this->add($property);
$updated = true;
}
} else {
2014-03-18 15:16:34 +01:00
if(!isset($this->{$property->name})) {
$this->add($property);
$updated = true;
} else {
$this->setPropertyByName($property->name, $property->getValue(), $property->parameters);
}
}
}
$this->setSaved(!$updated);
return $updated;
}
2014-03-23 19:02:16 +01:00
public function __get($key) {
2014-04-24 18:32:33 +02:00
if (!$this->isRetrieved()) {
2013-09-24 13:39:45 +02:00
$this->retrieve();
}
return parent::__get($key);
}
2014-03-23 19:02:16 +01:00
public function __isset($key) {
2014-04-24 18:32:33 +02:00
if (!$this->isRetrieved()) {
2013-09-24 13:39:45 +02:00
$this->retrieve();
}
return parent::__isset($key);
}
2013-03-25 17:10:21 +01:00
public function __set($key, $value) {
2014-04-24 18:32:33 +02:00
if (!$this->isRetrieved()) {
2013-09-24 13:39:45 +02:00
$this->retrieve();
}
2013-03-25 17:10:21 +01:00
parent::__set($key, $value);
2014-04-24 18:32:33 +02:00
if ($key === 'FN') {
$this->props['displayname'] = $value;
}
2013-03-25 17:10:21 +01:00
$this->setSaved(false);
}
public function __unset($key) {
2014-04-24 18:32:33 +02:00
if (!$this->isRetrieved()) {
2013-09-24 13:39:45 +02:00
$this->retrieve();
}
parent::__unset($key);
2014-04-24 18:32:33 +02:00
if ($key === 'PHOTO') {
Properties::cacheThumbnail(
$this->getBackend()->name,
$this->getParent()->getId(),
$this->getId(),
null,
2014-03-21 15:17:36 +01:00
$this,
array('remove' => true)
);
}
2013-03-25 17:10:21 +01:00
$this->setSaved(false);
}
public function setRetrieved($state) {
2013-03-25 17:10:21 +01:00
$this->props['retrieved'] = $state;
}
public function isRetrieved() {
2013-03-25 17:10:21 +01:00
return $this->props['retrieved'];
}
public function setSaved($state = true) {
2013-03-25 17:10:21 +01:00
$this->props['saved'] = $state;
}
public function isSaved() {
2013-03-25 17:10:21 +01:00
return $this->props['saved'];
}
/**
* Generate an event to show in the calendar
*
* @return \Sabre\VObject\Component\VCalendar|null
*/
public function getBirthdayEvent() {
2014-04-24 18:32:33 +02:00
if (!isset($this->BDAY)) {
return;
}
$birthday = $this->BDAY;
if ((string)$birthday) {
$title = str_replace('{name}',
strtr((string)$this->FN, array('\,' => ',', '\;' => ';')),
App::$l10n->t('{name}\'s Birthday')
);
try {
$date = new \DateTime($birthday);
} catch(\Exception $e) {
return;
}
$vcal = new \Sabre\VObject\Component\VCalendar();
$vcal->VERSION = '2.0';
$vcal->createComponent('VEVENT');
$vevent->add('DTSTART');
$vevent->DTSTART->setDateTime(
$date
);
$event->DTSTART['VALUE'] = 'date';
$vevent->add('DURATION', 'P1D');
$vevent->{'UID'} = $this->UID;
$vevent->{'RRULE'} = 'FREQ=YEARLY';
2014-02-08 19:22:22 +01:00
$vevent->{'SUMMARY'} = $title . ' (' . $date->format('Y') . ')';
2015-04-27 17:35:25 +02:00
$vevent->{'TRANSP'} = 'TRANSPARENT';
$appinfo = \OCP\App::getAppInfo('contacts');
$appversion = \OCP\App::getAppVersion('contacts');
$vcal->PRODID = '-//ownCloud//NONSGML '.$appinfo['name'].' '.$appversion.'//EN';
$vcal->add($vevent);
return $vcal;
}
}
}