1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2025-01-18 07:52:21 +01:00

Merge branch 'master' of https://github.com/owncloud/contacts into ldap

This commit is contained in:
babelouest 2014-04-15 11:13:05 -04:00
commit b8c3c4e1ea
13 changed files with 751 additions and 35 deletions

View File

@ -68,3 +68,4 @@ if (\OCP\User::isLoggedIn()) {
} }
} }
} }

View File

@ -345,4 +345,130 @@
</declaration> </declaration>
</table> </table>
<table>
<name>*dbprefix*contacts_ocu_cards</name>
<declaration>
<field>
<name>id</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</length>
</field>
<field>
<name>owner</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</length>
</field>
<field>
<name>addressbookid</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<unsigned>true</unsigned>
<length>4</length>
</field>
<field>
<name>fullname</name>
<type>text</type>
<default></default>
<notnull>false</notnull>
<length>255</length>
</field>
<field>
<name>carddata</name>
<type>clob</type>
<notnull>false</notnull>
</field>
<field>
<name>uri</name>
<type>text</type>
<default></default>
<notnull>false</notnull>
<length>200</length>
</field>
<field>
<name>lastmodified</name>
<type>integer</type>
<default></default>
<notnull>false</notnull>
<unsigned>true</unsigned>
<length>4</length>
</field>
</declaration>
</table>
<table>
<name>*dbprefix*contacts_ocu_cards_properties</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>4</length>
</field>
<field>
<name>addressbookid</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</length>
</field>
<field>
<name>contactid</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</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>
</declaration>
</table>
</database> </database>

View File

@ -1 +1 @@
0.3.0.1 0.3.0.14

View File

@ -31,6 +31,12 @@ OC.Contacts = OC.Contacts || {};
if(!this.hasPermission(OC.PERMISSION_UPDATE)) { if(!this.hasPermission(OC.PERMISSION_UPDATE)) {
this.$li.find('a.action.edit').hide(); this.$li.find('a.action.edit').hide();
} }
if(!this.hasPermission(OC.PERMISSION_SHARE)) {
this.$li.find('a.action.share').hide();
}
if(['local', 'ldap'].indexOf(this.getBackend() === -1)) {
this.$li.find('a.action.carddav').hide();
}
this.$li.find('input:checkbox').prop('checked', this.book.active).on('change', function() { this.$li.find('input:checkbox').prop('checked', this.book.active).on('change', function() {
console.log('activate', self.getId()); console.log('activate', self.getId());
var checkbox = $(this).get(0); var checkbox = $(this).get(0);
@ -55,7 +61,7 @@ OC.Contacts = OC.Contacts || {};
console.log('delete', self.getId()); console.log('delete', self.getId());
self.destroy(); self.destroy();
}); });
this.$li.find('a.action.globe').on('click keypress', function() { this.$li.find('a.action.carddav').on('click keypress', function() {
var uri = (self.book.owner === oc_current_user ) ? self.book.uri : self.book.uri + '_shared_by_' + self.book.owner; var uri = (self.book.owner === oc_current_user ) ? self.book.uri : self.book.uri + '_shared_by_' + self.book.owner;
var link = OC.linkToRemote('carddav')+'/addressbooks/'+encodeURIComponent(oc_current_user)+'/'+encodeURIComponent(uri); var link = OC.linkToRemote('carddav')+'/addressbooks/'+encodeURIComponent(oc_current_user)+'/'+encodeURIComponent(uri);
var $dropdown = $('<li><div id="dropdown" class="drop"><input type="text" value="{link}" readonly /></div></li>') var $dropdown = $('<li><div id="dropdown" class="drop"><input type="text" value="{link}" readonly /></div></li>')

View File

@ -1488,15 +1488,18 @@ OC.Contacts = OC.Contacts || {};
} }
} }
}); });
if(this.metadata.owner !== OC.currentUser var actions = ['close', 'export'];
&& !(this.hasPermission(OC.PERMISSION_UPDATE) if(this.hasPermission(OC.PERMISSION_DELETE)) {
|| this.hasPermission(OC.PERMISSION_DELETE))) { actions.push('delete');
this.setEnabled(false);
this.showActions(['close', 'export']);
} else {
this.setEnabled(true);
this.showActions(['close', 'add', 'export', 'delete']);
} }
if(this.hasPermission(OC.PERMISSION_UPDATE)) {
actions.push('add');
this.setEnabled(true);
} else {
this.setEnabled(false);
}
this.showActions(actions);
return this.$fullelem; return this.$fullelem;
}; };

View File

@ -174,7 +174,7 @@
"Address books" => "Adresáře kontaktů", "Address books" => "Adresáře kontaktů",
"Display name" => "Zobrazované jméno", "Display name" => "Zobrazované jméno",
"Add Address Book" => "Přidat adresář kontaktů", "Add Address Book" => "Přidat adresář kontaktů",
"Automatic format" => "Automatícký formát", "Automatic format" => "Automatický formát",
"Select file..." => "Vybrat soubor...", "Select file..." => "Vybrat soubor...",
"(De-)select all" => "Vybrat (odznačit) vše", "(De-)select all" => "Vybrat (odznačit) vše",
"Sort order" => "Řazení", "Sort order" => "Řazení",

View File

@ -18,9 +18,9 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ownCloud\n" "Project-Id-Version: ownCloud\n"
"Report-Msgid-Bugs-To: translations@owncloud.org\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n"
"POT-Creation-Date: 2014-04-08 00:50-0400\n" "POT-Creation-Date: 2014-04-15 00:48-0400\n"
"PO-Revision-Date: 2014-04-08 04:50+0000\n" "PO-Revision-Date: 2014-04-14 05:00+0000\n"
"Last-Translator: I Robot\n" "Last-Translator: pstast <petr@stastny.eu>\n"
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -116,7 +116,7 @@ msgstr "Sloučení selhalo. Chyba při ukládání kontaktu."
msgid "Select photo" msgid "Select photo"
msgstr "Vybrat fotku" msgstr "Vybrat fotku"
#: js/app.js:705 js/app.js:1675 #: js/app.js:705 js/app.js:1679
msgid "Network or server error. Please inform administrator." msgid "Network or server error. Please inform administrator."
msgstr "Chyba sítě či serveru. Kontaktujte prosím správce." msgstr "Chyba sítě či serveru. Kontaktujte prosím správce."
@ -167,11 +167,11 @@ msgstr "OK"
msgid "Could not find contact: {id}" msgid "Could not find contact: {id}"
msgstr "Nelze nalézt kontakt: {id}" msgstr "Nelze nalézt kontakt: {id}"
#: js/app.js:1630 #: js/app.js:1634
msgid "Edit profile picture" msgid "Edit profile picture"
msgstr "Upravit obrázek profilu" msgstr "Upravit obrázek profilu"
#: js/app.js:1634 #: js/app.js:1638
msgid "Crop photo" msgid "Crop photo"
msgstr "Oříznout fotku" msgstr "Oříznout fotku"
@ -191,17 +191,17 @@ msgstr "Chyba parsování narozenin {bday}"
msgid "The backend does not support multi-byte characters." msgid "The backend does not support multi-byte characters."
msgstr "Úložiště nepodporuje více-bajtové znaky." msgstr "Úložiště nepodporuje více-bajtové znaky."
#: js/contacts.js:2222 #: js/contacts.js:2224
msgid "" msgid ""
"Some contacts are marked for deletion, but not deleted yet. Please wait for " "Some contacts are marked for deletion, but not deleted yet. Please wait for "
"them to be deleted." "them to be deleted."
msgstr "Některé kontakty jsou označeny ke smazání, ale ještě smazány nejsou. Počkejte, prosím, na dokončení operace." msgstr "Některé kontakty jsou označeny ke smazání, ale ještě smazány nejsou. Počkejte, prosím, na dokončení operace."
#: js/contacts.js:2233 #: js/contacts.js:2235
msgid "Click to undo deletion of {num} contacts" msgid "Click to undo deletion of {num} contacts"
msgstr "Klikněte pro navrácení smazání {num} kontaktů" msgstr "Klikněte pro navrácení smazání {num} kontaktů"
#: js/contacts.js:2242 #: js/contacts.js:2244
msgid "Cancelled deletion of {num} contacts" msgid "Cancelled deletion of {num} contacts"
msgstr "Smazání {num} kontaktů zrušeno" msgstr "Smazání {num} kontaktů zrušeno"
@ -388,49 +388,49 @@ msgstr "Neznámý komunikátor: "
msgid "{name}'s Birthday" msgid "{name}'s Birthday"
msgstr "Narozeniny {name}" msgstr "Narozeniny {name}"
#: lib/controller/addressbookcontroller.php:163 #: lib/controller/addressbookcontroller.php:175
msgid "Error creating address book" msgid "Error creating address book"
msgstr "Chyba při vytváření adresáře kontaktů" msgstr "Chyba při vytváření adresáře kontaktů"
#: lib/controller/addressbookcontroller.php:195 #: lib/controller/addressbookcontroller.php:207
#, php-format #, php-format
msgid "The \"%s\" backend does not support deleting address books" msgid "The \"%s\" backend does not support deleting address books"
msgstr "Toto uložiště \"%s\" nepodporuje mazání adresářů kontaktů" msgstr "Toto uložiště \"%s\" nepodporuje mazání adresářů kontaktů"
#: lib/controller/addressbookcontroller.php:203 #: lib/controller/addressbookcontroller.php:215
#, php-format #, php-format
msgid "You do not have permissions to delete the \"%s\" address book" msgid "You do not have permissions to delete the \"%s\" address book"
msgstr "Nemáte oprávnění pro smazání adresáře kontaktů \"%s\"" msgstr "Nemáte oprávnění pro smazání adresáře kontaktů \"%s\""
#: lib/controller/addressbookcontroller.php:210 #: lib/controller/addressbookcontroller.php:222
msgid "Error deleting address book" msgid "Error deleting address book"
msgstr "Chyba při mazání adresáře kontaktů" msgstr "Chyba při mazání adresáře kontaktů"
#: lib/controller/addressbookcontroller.php:250 #: lib/controller/addressbookcontroller.php:262
msgid "Error creating contact." msgid "Error creating contact."
msgstr "Chyba při vytváření kontaktu" msgstr "Chyba při vytváření kontaktu"
#: lib/controller/addressbookcontroller.php:259 #: lib/controller/addressbookcontroller.php:271
msgid "Error creating contact" msgid "Error creating contact"
msgstr "Chyba při vytváření kontaktu" msgstr "Chyba při vytváření kontaktu"
#: lib/controller/addressbookcontroller.php:291 #: lib/controller/addressbookcontroller.php:303
msgid "Error deleting contact" msgid "Error deleting contact"
msgstr "Chyba při odstraňování kontaktu" msgstr "Chyba při odstraňování kontaktu"
#: lib/controller/addressbookcontroller.php:331 #: lib/controller/addressbookcontroller.php:343
msgid "Error retrieving contact" msgid "Error retrieving contact"
msgstr "Chyba při otevírání kontaktu" msgstr "Chyba při otevírání kontaktu"
#: lib/controller/addressbookcontroller.php:342 #: lib/controller/addressbookcontroller.php:354
msgid "Error saving contact" msgid "Error saving contact"
msgstr "Chyba při ukládání kontaktu" msgstr "Chyba při ukládání kontaktu"
#: lib/controller/addressbookcontroller.php:348 #: lib/controller/addressbookcontroller.php:360
msgid "Error removing contact from other address book." msgid "Error removing contact from other address book."
msgstr "Chyba při odebírání kontaktu z jiného adresáře kontaktů." msgstr "Chyba při odebírání kontaktu z jiného adresáře kontaktů."
#: lib/controller/addressbookcontroller.php:355 #: lib/controller/addressbookcontroller.php:367
msgid "Error getting moved contact" msgid "Error getting moved contact"
msgstr "Chyba při získávání přesunutého kontaktu" msgstr "Chyba při získávání přesunutého kontaktu"
@ -753,7 +753,7 @@ msgstr "Přidat adresář kontaktů"
#: templates/contacts.php:35 #: templates/contacts.php:35
msgid "Automatic format" msgid "Automatic format"
msgstr "Automatícký formát" msgstr "Automatický formát"
#: templates/contacts.php:44 templates/contacts.php:45 #: templates/contacts.php:44 templates/contacts.php:45
msgid "Select file..." msgid "Select file..."

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ownCloud contacts 5.0.0\n" "Project-Id-Version: ownCloud contacts 5.0.0\n"
"Report-Msgid-Bugs-To: translations@owncloud.org\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n"
"POT-Creation-Date: 2014-04-14 00:48-0400\n" "POT-Creation-Date: 2014-04-15 00:48-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -57,6 +57,7 @@ class App {
'ldap' => 'OCA\Contacts\Backend\Ldap', 'ldap' => 'OCA\Contacts\Backend\Ldap',
'local' => 'OCA\Contacts\Backend\Database', 'local' => 'OCA\Contacts\Backend\Database',
'shared' => 'OCA\Contacts\Backend\Shared', 'shared' => 'OCA\Contacts\Backend\Shared',
'localusers' => 'OCA\Contacts\Backend\LocalUsers',
); );
public function __construct( public function __construct(

View File

@ -439,7 +439,7 @@ class Database extends AbstractBackend {
} }
} }
return $cards; return $cards;
} }
@ -1018,4 +1018,9 @@ class Database extends AbstractBackend {
return self::$preparedQueries[$identifier]; return self::$preparedQueries[$identifier];
} }
public function getSearchProvider($addressbook){
return new \OCA\Contacts\AddressbookProvider($addressbook);
}
} }

411
lib/backend/localusers.php Normal file
View File

@ -0,0 +1,411 @@
<?php
/**
* ownCloud - ownCloud users backend for Contacts
*
* @author Tobia De Koninck
* @copyright 2014 Tobia De Koninck (tobia@ledfan.be)
*
* 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\Backend;
use OCA\Contacts\Contact,
OCA\Contacts\VObject\VCard,
OCA\Contacts\Utils\Properties,
Sabre\VObject\Reader,
OCA\Contacts\Addressbook,
OCA\Contacts\LocalUsersAddressbookProvider;
/**
* Contact backend for storing all the ownCloud users in this installation.
* Every user has *1* personal addressbook. The id of this addresbook is the
* userid of the owner.
*/
class LocalUsers extends AbstractBackend {
public $name = 'localusers';
/**
* The table that holds the address books.
* For every user there is *1* addressbook.
* @var string
*/
private $addressBooksTableName = '*PREFIX*contacts_ocu_addressbooks';
/**
* The table that holds the contacts.
* @var string
*/
private $cardsTableName = '*PREFIX*contacts_ocu_cards';
/**
* The table that holds the properties of the contacts.
* This is used to provice a search function.
* @var string
*/
private $indexTableName = '*PREFIX*contacts_ocu_cards_properties';
/**
* All possible properties which can be stored in the $indexTableName.
* @var string
*/
private $indexProperties = array(
'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME',
'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO');
/**
* language object
* @var OC_L10N
*/
public static $l10n;
/**
* Defaults object
* @var OC_Defaults
*/
public static $defaults;
public function __construct($userid){
self::$l10n = \OCP\Util::getL10N('contacts');
self::$defaults = new \OCP\Defaults();
$this->userid = $userid ? $userid : \OCP\User::getUser();
}
/**
* {@inheritdoc}
*/
public function getAddressBooksForUser(array $options = array()) {
return array($this->getAddressBook($this->userid));
}
/**
* {@inheritdoc}
* Only 1 addressbook for every user
*/
public function getAddressBook($addressBookId, array $options = array()) {
$addressbook = array(
"id" => $addressBookId,
"displayname" => self::$l10n->t('On this') . self::$defaults->getName(),
"description" => self::$l10n->t('On this') . self::$defaults->getName(),
"ctag" => time(),
"permissions" => \OCP\PERMISSION_READ,
"backend" => $this->name,
"active" => 1
);
return $addressbook;
}
/**
* {@inheritdoc}
* There are as many contacts in this addressbook as in this ownCloud installation
*/
public function getContacts($addressbookid, array $options = array()){
$this->updateDatabase();
$contacts = array();
try{
$sql = 'SELECT * FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?';
$query = \OCP\DB::prepare($sql);
$result = $query->execute(array($this->userid));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return true;
} else {
while($row = $result->fetchRow()){
$row['permissions'] = \OCP\PERMISSION_READ | \OCP\PERMISSION_UPDATE;
$contacts[] = $row;
}
}
return $contacts;
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.' exception: '
. $e->getMessage(), \OCP\Util::ERROR);
return array();
}
}
/**
* {@inheritdoc}
* If your username is "admin" and you want to retrieve your own contact
* the params would be: $addressbookid = 'admin'; $id = 'admin';
* If your username is 'foo' and you want to retrieve the contact with
* ownCloud username 'bar' the params would be: $addressbookid = 'foo'; $id = 'bar';
*/
public function getContact($addressbookid, $id, array $options = array()){
try{
$sql = 'SELECT * FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND id = ?';
$query = \OCP\DB::prepare($sql);
$result = $query->execute(array($this->userid, $id));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return array();
} else {
$row = $result->fetchRow();
$row['permissions'] = \OCP\PERMISSION_READ | \OCP\PERMISSION_UPDATE;
return $row;
}
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.' exception: '
. $e->getMessage(), \OCP\Util::ERROR);
return array();
}
}
/**
* Help function to add contacts to an addressbook.
* This only happens when an admin creates new users
* @param array $contacts array with userid of ownCloud users
* @param string $addressBookId
* @return bool
*/
private function addContacts($contacts, $addressbookid){
foreach($contacts as $user){
try{
$sql = 'INSERT INTO ' . $this->cardsTableName . ' ('
. 'id, '
. 'addressbookid, '
. 'fullname, '
. 'carddata, '
. 'lastmodified'
. ') VALUES ('
. '?,'
. '?,'
. '?,'
. '?,'
. '?'
. ')';
$query = \OCP\DB::prepare($sql);
$vcard = \Sabre\VObject\Component::create('VCARD');
$vcard->FN = \OCP\User::getDisplayName($user);
$now = new \DateTime('now');
$vcard->REV = $now->format(\DateTime::W3C);
$appinfo = \OCP\App::getAppInfo('contacts');
$appversion = \OCP\App::getAppVersion('contacts');
$prodid = '-//ownCloud//NONSGML ' . $appinfo['name'] . ' ' . $appversion.'//EN';
$vcard->PRODID = $prodid;
$vcard->add('IMPP', 'x-owncloud-handle:' . $user, array("X-SERVICE-TYPE" => array("owncloud-handle")));
$result = $query->execute(array($user, $this->userid, \OCP\User::getDisplayName($user), $vcard->serialize(), time()));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return false;
} else {
// All done
// now update the index table with all the properties
$this->updateIndex($user, $vcard);
return true;
}
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.' exception: '
. $e->getMessage(), \OCP\Util::ERROR);
return false;
}
}
}
/**
* Help function to remove contacts from an addressbook.
* This only happens when an admin remove an ownCloud user
* @param array $contacts array with userid of ownCloud users
* @param string $addressBookId
* @return bool
*/
private function removeContacts($contacts, $addressbookid){
foreach($contacts as $user){
try{
$sql = 'DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND id = ?';
$query = \OCP\DB::prepare($sql);
$result = $query->execute(array($this->userid, $user));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return false;
} else {
return true;
}
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.' exception: '
. $e->getMessage(), \OCP\Util::ERROR);
return false;
}
}
}
/**
* @inheritdoc
*/
public function updateContact($addressBookId, $id, $contact, array $options = array()) {
$updateRevision = true;
$isCardDAV = false;
if (!$contact instanceof VCard) {
try {
$contact = Reader::read($contact);
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
return false;
}
}
if ($updateRevision || !isset($contact->REV)) {
$now = new \DateTime;
$contact->REV = $now->format(\DateTime::W3C);
}
try{
$sql = 'UPDATE ' . $this->cardsTableName
. ' SET '
. '`fullname` = ?, '
. '`carddata` = ?, '
. '`lastmodified` = ? '
. ' WHERE '
. '`id` = ? '
. 'AND `addressbookid` = ? ';
$query = \OCP\DB::prepare($sql);
$result = $query->execute(array($contact->FN, $contact->serialize(), time(), $id, $this->userid));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return false;
} else {
// All done
// now update the indexes in the DB
$this->updateIndex($id, $contact);
return true;
}
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.' exception: '
. $e->getMessage(), \OCP\Util::ERROR);
return false;
}
}
/**
* This is a hack so backends can have different search functions.
* @return \OCA\Contacts\LocalUsersAddressbookProvider
*/
public function getSearchProvider(){
return new LocalUsersAddressbookProvider($this);
}
/**
* Updates the index table. All properties of a contact are stored in it.
* Needed for the search function.
* @param type $contactId
* @param type $vcard
* @return boolean
*/
private function updateIndex($contactId, $vcard){
// Utils\Properties::updateIndex($parameters['id'], $contact);
$this->purgeIndex($contactId);
$updatestmt = \OCP\DB::prepare('INSERT INTO `' . $this->indexTableName . '` '
. '(`addressbookid`, `contactid`,`name`,`value`,`preferred`) VALUES(?,?,?,?,?)');
// Insert all properties in the table
foreach($vcard->children as $property) {
if(!in_array($property->name, $this->indexProperties)) {
continue;
}
$preferred = 0;
foreach($property->parameters as $parameter) {
if($parameter->name == 'TYPE' && strtoupper($parameter->value) == 'PREF') {
$preferred = 1;
break;
}
}
try {
$result = $updatestmt->execute(
array(
\OCP\User::getUser(),
$contactId,
$property->name,
substr($property->value, 0, 254),
$preferred,
)
);
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return false;
}
} catch(\Exception $e) {
\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
return false;
}
}
}
/**
* Remove all indexes from the table.
* This is always called before adding new properties.
* @param type $contactId
* @param type $vcard
* @return boolean
*/
private function purgeIndex($id){
// Remove all indexes from the table
try {
$query = \OCP\DB::prepare('DELETE FROM `' . $this->indexTableName . '`'
. ' WHERE `contactid` = ?');
$query->execute(array($id));
} catch(\Exception $e) {
return false;
}
}
public function updateDatabase(){
$sql = 'SELECT * FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?';
$query = \OCP\DB::prepare($sql);
$result = $query->execute(array($this->userid));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
return true;
} else {
$contactsId = array();
while($row = $result->fetchRow()){
$contactsId[] = $row['id'];
}
$users = \OCP\User::getUsers();
$add = array_diff($users, $contactsId);
$remove = array_diff($contactsId, $users);
if(count($add) > 0){
$this->addContacts($add, $addressbookid);
$recall = true;
}
if(count($remove) > 0){
$this->removeContacts($remove, $addressbookid);
$recall = true;
}
return true;
}
}
}

View File

@ -0,0 +1,163 @@
<?php
namespace OCA\Contacts;
use OCA\Contacts\Utils\Properties;
use OCA\Contacts\Backend\LocalUsers;
class LocalUsersAddressbookProvider implements \OCP\IAddressBook {
/**
* The table that holds the address books.
* For every user there is *1* addressbook.
* @var string
*/
private $addressBooksTableName = '*PREFIX*contacts_ocu_addressbooks';
/**
* The table that holds the contacts.
* @var string
*/
private $cardsTableName = '*PREFIX*contacts_ocu_cards';
/**
* The table that holds the properties of the contacts.
* This is used to provice a search function.
* @var string
*/
private $indexTableName = '*PREFIX*contacts_ocu_cards_properties';
/**
* @var LocalUsers
*/
private $backend;
public function __construct(LocalUsers $backend){
$this->backend = $backend;
}
/**
* @param $pattern
* @param $searchProperties
* @param $options
* @return array|false
*/
public function search($pattern, $searchProperties, $options) {
// First make sure the database is updated
$this->backend->updateDatabase();
$ids = array();
$results = array();
$query = 'SELECT DISTINCT `contactid` FROM `' . $this->indexTableName . '` WHERE (';
$params = array();
foreach($searchProperties as $property) {
$params[] = $property;
$params[] = '%' . $pattern . '%';
$query .= '(`name` = ? AND `value` LIKE ?) OR ';
}
$query = substr($query, 0, strlen($query) - 4);
$query .= ')';
$stmt = \OCP\DB::prepare($query);
$result = $stmt->execute($params);
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('contacts', __METHOD__ . 'DB error: ' . \OC_DB::getErrorMessage($result),
\OCP\Util::ERROR);
return false;
}
while( $row = $result->fetchRow()) {
$ids[] = $row['contactid'];
}
if(count($ids) > 0) {
$query = 'SELECT `' . $this->cardsTableName . '`.`addressbookid`, `' . $this->indexTableName . '`.`contactid`, `'
. $this->indexTableName . '`.`name`, `' . $this->indexTableName . '`.`value` FROM `'
. $this->indexTableName . '`,`' . $this->cardsTableName . '` WHERE `'
. $this->cardsTableName . '`.`addressbookid` = \'' . \OCP\User::getUser() . '\' AND `'
. $this->indexTableName . '`.`contactid` = `' . $this->cardsTableName . '`.`id` AND `'
. $this->indexTableName . '`.`contactid` IN (' . join(',', array_fill(0, count($ids), '?')) . ')';
$stmt = \OCP\DB::prepare($query);
$result = $stmt->execute($ids);
}
while( $row = $result->fetchRow()) {
$this->getProperty($results, $row);
}
return $results;
}
public function getKey(){
}
/**
* In comparison to getKey() this function returns a human readable (maybe translated) name
* @return mixed
*/
public function getDisplayName(){
}
public function createOrUpdate($properties){
}
/**
* @return mixed
*/
public function getPermissions(){
}
/**
* @param object $id the unique identifier to a contact
* @return bool successful or not
*/
public function delete($id){
}
private function getProperty(&$results, $row) {
if(!$row['name'] || !$row['value']) {
return false;
}
$value = null;
switch($row['name']) {
case 'PHOTO':
$value = 'VALUE=uri:' . \OCP\Util::linkToAbsolute('contacts', 'photo.php') . '?id=' . $row['contactid'];
break;
case 'N':
case 'ORG':
case 'ADR':
case 'GEO':
case 'CATEGORIES':
$property = \Sabre\VObject\Property::create($row['name'], $row['value']);
$value = $property->getParts();
break;
default:
$value = $value = strtr($row['value'], array('\,' => ',', '\;' => ';'));
break;
}
if(in_array($row['name'], Properties::$multiProperties)) {
if(!isset($results[$row['contactid']])) {
$results[$row['contactid']] = array('id' => $row['contactid'], $row['name'] => array($value));
} elseif(!isset($results[$row['contactid']][$row['name']])) {
$results[$row['contactid']][$row['name']] = array($value);
} else {
$results[$row['contactid']][$row['name']][] = $value;
}
} else {
if(!isset($results[$row['contactid']])) {
$results[$row['contactid']] = array('id' => $row['contactid'], $row['name'] => $value);
} elseif(!isset($results[$row['contactid']][$row['name']])) {
$results[$row['contactid']][$row['name']] = $value;
}
}
}
}

View File

@ -504,7 +504,7 @@ use OCA\Contacts\ImportManager;
<span class="actions"> <span class="actions">
<a title="<?php p($l->t('Share')); ?>" class="icon-share share action" data-possible-permissions="{permissions}" data-item="{id}" data-item-type="addressbook"></a> <a title="<?php p($l->t('Share')); ?>" class="icon-share share action" data-possible-permissions="{permissions}" data-item="{id}" data-item-type="addressbook"></a>
<a title="<?php p($l->t('Export')); ?>" class="icon-download download action"></a> <a title="<?php p($l->t('Export')); ?>" class="icon-download download action"></a>
<a title="<?php p($l->t('CardDAV link')); ?>" class="icon-public globe action"></a> <a title="<?php p($l->t('CardDAV link')); ?>" class="icon-public carddav action"></a>
<a title="<?php p($l->t('Edit')); ?>" class="icon-rename edit action"></a> <a title="<?php p($l->t('Edit')); ?>" class="icon-rename edit action"></a>
<a title="<?php p($l->t('Delete')); ?>" class="icon-delete delete action"></a> <a title="<?php p($l->t('Delete')); ?>" class="icon-delete delete action"></a>
</span> </span>