2012-12-12 00:07:36 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* ownCloud - AddressbookProvider
|
|
|
|
*
|
|
|
|
* @author Thomas Tanghus
|
2014-01-26 00:40:22 +01:00
|
|
|
* @copyright 2012-2014 Thomas Tanghus (thomas@tanghus.net)
|
2012-12-12 00:07:36 +01:00
|
|
|
*
|
|
|
|
* 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;
|
2014-07-22 12:42:59 +02:00
|
|
|
use OCA\Contacts\Utils\JSONSerializer;
|
2013-04-30 02:05:15 +02:00
|
|
|
use OCA\Contacts\Utils\Properties;
|
2014-07-22 12:42:59 +02:00
|
|
|
use OCA\Contacts\Utils\TemporaryPhoto;
|
|
|
|
use OCA\Contacts\VObject\VCard;
|
2012-12-12 00:07:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This class manages our addressbooks.
|
2013-03-20 11:27:40 +01:00
|
|
|
* TODO: Port this to use the new backend
|
2012-12-12 00:07:36 +01:00
|
|
|
*/
|
|
|
|
class AddressbookProvider implements \OCP\IAddressBook {
|
|
|
|
|
|
|
|
const CONTACT_TABLE = '*PREFIX*contacts_cards';
|
|
|
|
const PROPERTY_TABLE = '*PREFIX*contacts_cards_properties';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Addressbook id
|
|
|
|
* @var integer
|
|
|
|
*/
|
|
|
|
public $id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Addressbook info array
|
2013-04-30 02:05:15 +02:00
|
|
|
* @var AddressBook
|
2012-12-12 00:07:36 +01:00
|
|
|
*/
|
2013-04-30 02:05:15 +02:00
|
|
|
public $addressBook;
|
2012-12-12 00:07:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
2014-04-17 04:59:14 +02:00
|
|
|
* @param AddressBook $addressBook
|
2012-12-12 00:07:36 +01:00
|
|
|
*/
|
2013-04-30 02:05:15 +02:00
|
|
|
public function __construct($addressBook) {
|
|
|
|
$this->addressBook = $addressBook;
|
2014-11-21 11:05:06 +01:00
|
|
|
$this->app = new App();
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getAddressbook() {
|
2013-04-30 02:05:15 +02:00
|
|
|
return $this->addressBook;
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string defining the technical unique key
|
|
|
|
*/
|
|
|
|
public function getKey() {
|
2013-04-30 02:05:15 +02:00
|
|
|
$metaData = $this->addressBook->getMetaData();
|
|
|
|
return $metaData['backend'].':'.$metaData['id'];
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* In comparison to getKey() this function returns a human readable (maybe translated) name
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getDisplayName() {
|
2013-04-30 02:05:15 +02:00
|
|
|
return $this->addressBook->getDisplayName();
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getPermissions() {
|
2013-04-30 02:05:15 +02:00
|
|
|
return $this->addressBook->getPermissions();
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $pattern
|
|
|
|
* @param $searchProperties
|
|
|
|
* @param $options
|
|
|
|
* @return array|false
|
|
|
|
*/
|
|
|
|
public function search($pattern, $searchProperties, $options) {
|
2014-11-21 11:36:28 +01:00
|
|
|
$propTable = self::PROPERTY_TABLE;
|
|
|
|
$contTable = self::CONTACT_TABLE;
|
2012-12-12 00:07:36 +01:00
|
|
|
$results = array();
|
2014-11-21 11:36:28 +01:00
|
|
|
$query = <<<SQL
|
|
|
|
SELECT
|
|
|
|
DISTINCT
|
|
|
|
`$propTable`.`contactid`,
|
|
|
|
`$contTable`.`addressbookid`
|
|
|
|
FROM
|
|
|
|
`$propTable`
|
|
|
|
INNER JOIN
|
|
|
|
`$contTable`
|
|
|
|
ON `$contTable`.`id` = `$propTable`.`contactid`
|
|
|
|
WHERE
|
|
|
|
`$propTable`.`userid` = ?
|
|
|
|
AND (
|
|
|
|
SQL;
|
|
|
|
|
2014-09-25 08:08:50 +02:00
|
|
|
$params = array(\OCP\User::getUser());
|
2014-11-21 11:36:28 +01:00
|
|
|
foreach ($searchProperties as $property) {
|
2013-03-25 21:34:18 +01:00
|
|
|
$params[] = $property;
|
|
|
|
$params[] = '%' . $pattern . '%';
|
|
|
|
$query .= '(`name` = ? AND `value` LIKE ?) OR ';
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
$query = substr($query, 0, strlen($query) - 4);
|
|
|
|
$query .= ')';
|
|
|
|
|
|
|
|
$stmt = \OCP\DB::prepare($query);
|
2013-03-25 21:34:18 +01:00
|
|
|
$result = $stmt->execute($params);
|
2013-09-16 02:24:08 +02:00
|
|
|
if (\OCP\DB::isError($result)) {
|
|
|
|
\OCP\Util::writeLog('contacts', __METHOD__ . 'DB error: ' . \OC_DB::getErrorMessage($result),
|
2012-12-12 00:07:36 +01:00
|
|
|
\OCP\Util::ERROR);
|
|
|
|
return false;
|
|
|
|
}
|
2014-11-21 11:36:28 +01:00
|
|
|
while ($row = $result->fetchRow()) {
|
2014-11-21 11:06:54 +01:00
|
|
|
$id = $row['contactid'];
|
2014-11-21 11:36:28 +01:00
|
|
|
$addressbookKey = $row['addressbookid'];
|
2014-11-21 11:06:54 +01:00
|
|
|
try {
|
|
|
|
// gues that it is a local addressbook
|
|
|
|
$contact = $this->app->getContact('local', $addressbookKey, $id);
|
|
|
|
} catch (\Exception $e) {
|
2014-11-21 11:36:28 +01:00
|
|
|
if ($e->getCode() === 404) {
|
2014-11-21 11:06:54 +01:00
|
|
|
// not a local thus it is a shared
|
|
|
|
$contact = $this->app->getContact('shared', $addressbookKey, $id);
|
2014-07-22 12:42:59 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-21 11:06:54 +01:00
|
|
|
$j = JSONSerializer::serializeContact($contact);
|
|
|
|
$j['data']['id'] = $id;
|
|
|
|
if (isset($contact->PHOTO)) {
|
2014-11-21 11:36:28 +01:00
|
|
|
$url = \OCP\Util::linkToRoute('contacts_contact_photo',
|
2014-11-21 11:06:54 +01:00
|
|
|
array(
|
|
|
|
'backend' => $contact->getBackend()->name,
|
|
|
|
'addressBookId' => $this->addressBook->getId(),
|
|
|
|
'contactId' => $contact->getId()
|
|
|
|
));
|
|
|
|
$url = \OC_Helper::makeURLAbsolute($url);
|
|
|
|
$j['data']['PHOTO'] = "VALUE=uri:$url";
|
|
|
|
}
|
2014-11-21 11:36:28 +01:00
|
|
|
$results[] = $this->convertToSearchResult($j);
|
2012-12-12 00:07:36 +01:00
|
|
|
}
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $properties
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function createOrUpdate($properties) {
|
|
|
|
$id = null;
|
2014-03-21 14:18:40 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var \OCA\Contacts\VObject\VCard
|
|
|
|
*/
|
2012-12-12 00:07:36 +01:00
|
|
|
$vcard = null;
|
|
|
|
if(array_key_exists('id', $properties)) {
|
|
|
|
// TODO: test if $id belongs to this addressbook
|
|
|
|
$id = $properties['id'];
|
|
|
|
// TODO: Test $vcard
|
2014-03-20 21:52:07 +01:00
|
|
|
$vcard = $this->addressBook->getChild($properties['id']);
|
2012-12-12 00:07:36 +01:00
|
|
|
foreach(array_keys($properties) as $name) {
|
|
|
|
if(isset($vcard->{$name})) {
|
|
|
|
unset($vcard->{$name});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$vcard = \Sabre\VObject\Component::create('VCARD');
|
|
|
|
$uid = substr(md5(rand().time()), 0, 10);
|
|
|
|
$vcard->add('UID', $uid);
|
|
|
|
try {
|
2014-03-21 14:18:40 +01:00
|
|
|
$id = $this->addressBook->addChild($vcard);
|
2013-12-30 14:10:22 +01:00
|
|
|
} catch(\Exception $e) {
|
2013-09-16 02:24:08 +02:00
|
|
|
\OCP\Util::writeLog('contacts', __METHOD__ . ' ' . $e->getMessage(), \OCP\Util::ERROR);
|
2012-12-12 00:07:36 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach($properties as $name => $value) {
|
|
|
|
switch($name) {
|
|
|
|
case 'ADR':
|
|
|
|
case 'N':
|
|
|
|
if(is_array($value)) {
|
|
|
|
$property = \Sabre\VObject\Property::create($name);
|
|
|
|
$property->setParts($value);
|
|
|
|
$vcard->add($property);
|
|
|
|
} else {
|
|
|
|
$vcard->{$name} = $value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'BDAY':
|
|
|
|
// TODO: try/catch
|
|
|
|
$date = New \DateTime($value);
|
|
|
|
$vcard->BDAY = $date->format('Y-m-d');
|
|
|
|
$vcard->BDAY->VALUE = 'DATE';
|
|
|
|
break;
|
|
|
|
case 'EMAIL':
|
|
|
|
case 'TEL':
|
|
|
|
case 'IMPP': // NOTE: We don't know if it's GTalk, Jabber etc. only the protocol
|
|
|
|
case 'URL':
|
|
|
|
if(is_array($value)) {
|
|
|
|
foreach($value as $val) {
|
|
|
|
$vcard->add($name, strip_tags($val));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$vcard->add($name, strip_tags($value));
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
$vcard->{$name} = $value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
VCard::edit($id, $vcard);
|
2013-12-30 14:10:22 +01:00
|
|
|
} catch(\Exception $e) {
|
2013-09-16 02:24:08 +02:00
|
|
|
\OCP\Util::writeLog('contacts', __METHOD__ . ' ' . $e->getMessage(), \OCP\Util::ERROR);
|
2012-12-12 00:07:36 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$asarray = VCard::structureContact($vcard);
|
|
|
|
$asarray['id'] = $id;
|
|
|
|
return $asarray;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $id
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function delete($id) {
|
|
|
|
try {
|
2013-12-30 14:10:22 +01:00
|
|
|
$query = 'SELECT COUNT(*) as `count` FROM `*PREFIX*contacts_cards` WHERE `id` = ? AND `addressbookid` = ?';
|
2012-12-12 00:07:36 +01:00
|
|
|
$stmt = \OCP\DB::prepare($query);
|
|
|
|
$result = $stmt->execute(array($id, $this->id));
|
2013-09-16 02:24:08 +02:00
|
|
|
if (\OCP\DB::isError($result)) {
|
|
|
|
\OCP\Util::writeLog('contacts', __METHOD__ . 'DB error: ' . \OC_DB::getErrorMessage($result),
|
2012-12-12 00:07:36 +01:00
|
|
|
\OCP\Util::ERROR);
|
|
|
|
return false;
|
|
|
|
}
|
2013-12-30 14:10:22 +01:00
|
|
|
if((int)$result['count'] === 0) {
|
2013-09-16 02:24:08 +02:00
|
|
|
\OCP\Util::writeLog('contacts', __METHOD__
|
2012-12-12 00:07:36 +01:00
|
|
|
. 'Contact with id ' . $id . 'doesn\'t belong to addressbook with id ' . $this->id,
|
|
|
|
\OCP\Util::ERROR);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch(\Exception $e) {
|
|
|
|
\OCP\Util::writeLog('contacts', __METHOD__ . ', exception: ' . $e->getMessage(),
|
|
|
|
\OCP\Util::ERROR);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return VCard::delete($id);
|
|
|
|
}
|
2014-07-30 17:05:09 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $j
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function convertToSearchResult($j) {
|
|
|
|
$data = $j['data'];
|
|
|
|
$result = array();
|
|
|
|
foreach( $data as $key => $d) {
|
|
|
|
$d = $data[$key];
|
|
|
|
if (in_array($key, Properties::$multiProperties)) {
|
|
|
|
$result[$key] = array_map(function($v){
|
|
|
|
return $v['value'];
|
|
|
|
}, $d);
|
|
|
|
} else {
|
|
|
|
if (is_array($d)) {
|
|
|
|
$result[$key] = $d[0]['value'];
|
|
|
|
} else {
|
|
|
|
$result[$key] = $d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2014-11-21 11:05:06 +01:00
|
|
|
|
2012-12-12 21:39:58 +01:00
|
|
|
}
|