diff --git a/action/ajax.php b/action/ajax.php new file mode 100644 --- /dev/null +++ b/action/ajax.php @@ -0,0 +1,88 @@ +hlp =& plugin_load('helper','davcard'); + } + + function register(Doku_Event_Handler $controller) { + $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown'); + } + + function handle_ajax_call_unknown(&$event, $param) { + if($event->data != 'plugin_davcard') return; + + $event->preventDefault(); + $event->stopPropagation(); + global $INPUT; + + $action = trim($INPUT->post->str('action')); + $id = trim($INPUT->post->str('id')); + $page = trim($INPUT->post->str('page')); + $params = $INPUT->post->arr('params'); + if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) + $user = $_SERVER['REMOTE_USER']; + else + $user = null; + + if(!checkSecurityToken()) + { + echo "CSRF Attack."; + return; + } + + $data = array(); + + $data['result'] = false; + $data['html'] = $this->getLang('unknown_error'); + + // Parse the requested action + switch($action) + { + // Add a new Contact + case 'newContact': + if($this->hlp->addContactEntryToAddressbookForPage($id, $user, $params) === true) + { + $data['result'] = true; + } + else + { + $data['result'] = false; + $data['html'] = $this->getLang('error_adding'); + } + break; + + // Edit a contact + case 'editContact': + + break; + // Delete a Contact + case 'deleteContact': + + break; + } + + // If we are still here, JSON output is requested + + //json library of DokuWiki + require_once DOKU_INC . 'inc/JSON.php'; + $json = new JSON(); + + //set content type + header('Content-Type: application/json'); + echo $json->encode($data); + } + +} diff --git a/db/latest.version b/db/latest.version new file mode 100644 --- /dev/null +++ b/db/latest.version @@ -0,0 +1,1 @@ +1 \ No newline at end of file diff --git a/db/update0001.sql b/db/update0001.sql new file mode 100644 --- /dev/null +++ b/db/update0001.sql @@ -0,0 +1,36 @@ +CREATE TABLE addressbookobjects ( + id integer primary key asc, + contactdata blob, + uri text, + addressbookid integer, + lastmodified integer, + etag text, + size integer, + formattedname text, + structuredname text +); + +CREATE TABLE addressbookchanges ( + id integer primary key asc, + uri text, + synctoken integer, + addressbookid integer, + operation integer +); + +CREATE INDEX addressbookid_synctoken ON addressbookchanges (addressbookid, synctoken); + +CREATE TABLE pagetoaddressbookmapping ( + id integer primary key asc, + page text, + addressbookid integer +); + +CREATE TABLE addressbooks ( + id integer primary key asc, + principaluri text, + displayname text, + uri text, + synctoken integer, + description text +); diff --git a/helper.php b/helper.php --- a/helper.php +++ b/helper.php @@ -1,114 +1,379 @@ sqlite =& plugin_load('helper', 'sqlite'); + global $conf; + + if(!$this->sqlite) + { + if($conf['allowdebug']) + dbglog('This plugin requires the sqlite plugin. Please install it.'); + msg('This plugin requires the sqlite plugin. Please install it.'); + return; + } + if(!$this->sqlite->init('davcard', DOKU_PLUGIN.'davcard/db/')) + { + if($conf['allowdebug']) + dbglog('Error initialising the SQLite DB for DAVCard'); + return; + } } - public function getContactByName($id, $name) + public function getContactByStructuredName($id, $firstname = '', $lastname = '') + { + if(strpos($id, 'webdav://') === 0) + { + $wdc =& plugin_load('helper', 'webdavclient'); + if(is_null($wdc)) + return $this->getLang('no_wdc'); + $connectionId = str_replace('webdav://', '', $id); + $settings = $wdc->getConnection($connectionId); + + if($settings === false) + return $this->getLang('settings_not_found'); + if($settings['type'] !== 'contacts') + return $this->getLang('wrong_type'); + + $entries = $wdc->getAddressbookEntries($connectionId); + foreach($entries as $entry) + { + $contactdata = explode(';', $entry['structuredname']); + if(count($contactdata) != 5) // There MUST be five entries + continue; + if(($lastname != '') && ($contactdata[0] === $lastname) || $lastname === '') + { + // last name matched or no last name given + if(($firstname != '') && ($contactdata[1] === $firstname) || $firstname === '') + { + // first name matched too or no first name given + $info = $this->parseVcard($entry['contactdata']); + return $info; + } + } + } + } + return false; + } + + public function getContactByFormattedName($id, $name) { if(strpos($id, 'webdav://') === 0) { $wdc =& plugin_load('helper', 'webdavclient'); if(is_null($wdc)) return $this->getLang('no_wdc'); $connectionId = str_replace('webdav://', '', $id); $settings = $wdc->getConnection($connectionId); if($settings === false) return $this->getLang('settings_not_found'); if($settings['type'] !== 'contacts') return $this->getLang('wrong_type'); $entries = $wdc->getAddressbookEntries($connectionId); foreach($entries as $entry) { if(trim($entry['formattedname']) == $name) { $info = $this->parseVcard($entry['contactdata']); return $info; } } } return false; } public function getContactByUri($id) { } + public function setAddressbookNameForPage($name, $description, $id = null, $userid = null) + { + if(is_null($id)) + { + global $ID; + $id = $ID; + } + if(is_null($userid)) + { + if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) + { + $userid = $_SERVER['REMOTE_USER']; + } + else + { + $userid = uniqid('davcard-'); + } + } + $bookid = $this->getAddressbookIdForPage($id); + if($bookid === false) + return $this->createAddressbookForPage($name, $description, $id, $userid); + + $query = "UPDATE addressbooks SET displayname = ?, description = ? WHERE id = ?"; + $res = $this->sqlite->query($query, $name, $description, $bookid); + if($res !== false) + return true; + return false; + } + + public function getAddressbookIdForPage($id = null) + { + if(is_null($id)) + { + global $ID; + $id = $ID; + } + + $query = "SELECT addressbookid FROM pagetoaddressbookmapping WHERE page = ?"; + $res = $this->sqlite->query($query, $id); + $row = $this->sqlite->res2row($res); + if(isset($row['addressbookid'])) + { + $calid = $row['addressbookid']; + return $calid; + } + return false; + } + + public function createAddressbookForPage($name, $description, $id = null, $userid = null) + { + if(is_null($id)) + { + global $ID; + $id = $ID; + } + if(is_null($userid)) + { + if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) + { + $userid = $_SERVER['REMOTE_USER']; + } + else + { + $userid = uniqid('davcard-'); + } + } + $values = array('principals/'.$userid, + $name, + str_replace(array('/', ' ', ':'), '_', $id), + $description, + 1); + $query = "INSERT INTO addressbooks (principaluri, displayname, uri, description, synctoken) ". + "VALUES (?, ?, ?, ?, ?)"; + $res = $this->sqlite->query($query, $values); + if($res === false) + return false; + + // Get the new addressbook ID + $query = "SELECT id FROM addressbooks WHERE principaluri = ? AND displayname = ? AND ". + "uri = ? AND description = ? AND synctoken = ?"; + $res = $this->sqlite->query($query, $values); + $row = $this->sqlite->res2row($res); + + // Update the pagetocalendarmapping table with the new calendar ID + if(isset($row['id'])) + { + $query = "INSERT INTO pagetoaddressbookmapping (page, addressbookid) VALUES (?, ?)"; + $res = $this->sqlite->query($query, $id, $row['id']); + return ($res !== false); + } + + return false; + } + + public function addContactEntryToAddressbookForPage($id, $user, $params) + { + require_once(DOKU_PLUGIN.'davcard/vendor/autoload.php'); + + $vcard = new \Sabre\VObject\Component\VCard(); + $formattedname = $params['firstname'].' '.$params['lastname']; // FIXME: Make this configurable? + $structuredname = array($params['lastname'], $params['firstname'], '', '', ''); + $vcard->FN = $formattedname; + if($params['cellphone'] != '') + { + $vcard->add('TEL', $params['cellphone'], array('type' => 'cell')); + } + if($params['phone'] != '') + { + $vcard->add('TEL', $params['phone'], array('type' => 'home')); + } + $vcard->N = $structuredname; + + $vcard->add('ADR', array('', '', $params['street'], $params['city'], '', $params['zipcode'], $params['country']), array('type' => 'home')); + + $contactdata = $vcard->serialize(); + + if(strpos($id, 'webdav://') === 0) + { + $wdc =& plugin_load('helper', 'webdavclient'); + if(is_null($wdc)) + return false; + $connectionId = str_replace('webdav://', '', $id); + return $wdc->addAddressbookEntry($connectionId, $contactdata); + } + else + { + $addressbookid = $this->getAddressbookIdForPage($id); + $uri = uniqid('dokuwiki-').'.vcf'; + $now = new \DateTime(); + $query = "INSERT INTO addressbookobjects (contactdata, uri, addressbookid, lastmodified, etag, size, formattedname, structuredname) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + $res = $this->sqlite->query($query, + $contactdata, + $uri, + $addressbookid, + $now->getTimestamp(), + md5($contactdata), + strlen($contactdata), + $formattedname, + implode(';', $structuredname) + ); + // If successfully, update the sync token database + if($res !== false) + { + $this->updateSyncTokenLog($addressbookid, $uri, 'added'); + return true; + } + } + } + private function parseVcard($card) { require_once(DOKU_PLUGIN.'davcard/vendor/autoload.php'); $vObject = \Sabre\VObject\Reader::read($card); $formattedname = ''; $structuredname = ''; $tel = array(); $addr = array(); $mail = array(); if(isset($vObject->FN)) $formattedname = (string)$vObject->FN; if(isset($vObject->N)) $structuredname = join(';', $vObject->N->getParts()); if(isset($vObject->TEL)) { foreach($vObject->TEL as $number) { if(isset($number['TYPE'])) $tel[(string)$number['TYPE']] = (string)$number; else $tel[] = (string)$number; } } if(isset($vObject->ADR)) { foreach($vObject->ADR as $adr) { if(isset($adr['TYPE'])) $addr[(string)$adr['TYPE']] = $adr->getParts(); else $addr[] = $adr->getParts(); } } if(isset($vObject->EMAIL)) { foreach($vObject->EMAIL as $email) { if(isset($email['TYPE'])) $mail[(string)$email['TYPE']] = (string)$email; else $mail[] = (string)$email; } } return array( 'formattedname' => $formattedname, 'structuredname' => $structuredname, 'tel' => $tel, 'mail' => $mail, 'addr' => $addr ); } + + public function getAddressbookSettings($addressbookid) + { + $query = "SELECT id, principaluri, displayname, uri, description, synctoken FROM addressbooks WHERE id= ? "; + $res = $this->sqlite->query($query, $addressbookid); + $row = $this->sqlite->res2row($res); + return $row; + } + + public function getSyncTokenForAddressbook($addressbookid) + { + $row = $this->getAddressbookSettings($addressbookid); + if(isset($row['synctoken'])) + return $row['synctoken']; + return false; + } + + /** + * Helper function to convert the operation name to + * an operation code as stored in the database + * + * @param string $operationName The operation name + * + * @return mixed The operation code or false + */ + public function operationNameToOperation($operationName) + { + switch($operationName) + { + case 'added': + return 1; + break; + case 'modified': + return 2; + break; + case 'deleted': + return 3; + break; + } + return false; + } + private function updateSyncTokenLog($addressbookid, $uri, $operation) + { + $currentToken = $this->getSyncTokenForAddressbook($addressbookid); + $operationCode = $this->operationNameToOperation($operation); + if(($operationCode === false) || ($currentToken === false)) + return false; + $values = array($uri, + $currentToken, + $addressbookid, + $operationCode + ); + $query = "INSERT INTO addressbookchanges (uri, synctoken, addressbookid, operation) VALUES(?, ?, ?, ?)"; + $res = $this->sqlite->query($query, $uri, $currentToken, $addressbookid, $operationCode); + if($res === false) + return false; + $currentToken++; + $query = "UPDATE addressbooks SET synctoken = ? WHERE id = ?"; + $res = $this->sqlite->query($query, $currentToken, $addressbookid); + return ($res !== false); + } } diff --git a/lang/en/lang.php b/lang/en/lang.php --- a/lang/en/lang.php +++ b/lang/en/lang.php @@ -1,34 +1,58 @@ */ $lang['unknown_error'] = 'Unknown Error'; $lang['id_name_not_set'] = 'Either ID or Name must be set'; $lang['loading_via_ajax'] = 'Loadig Contact Data...'; $lang['no_wdc'] = 'Loading webdavclient PlugIn failed.'; $lang['settings_not_found'] = 'The requested WebDAV connection was not found'; $lang['wrong_type'] = 'The requested WebDAV connection is not of type contact'; $lang['contact_not_found'] = 'The requested contact was not found'; +$lang['error_adding'] = 'Error adding contact'; $lang['telvoice'] = 'Voice'; $lang['telhome'] = 'Home'; $lang['telmsg'] = 'Message'; $lang['telwork'] = 'Work'; $lang['telpref'] = 'preferred'; $lang['telfax'] = 'Fax'; $lang['telcell'] = 'Cell'; $lang['telvideo'] = 'Video'; $lang['telpager'] = 'Pager'; $lang['telbbs'] = 'BBS'; $lang['telmodem'] = 'Modem'; $lang['telcar'] = 'Car'; $lang['telisdn'] = 'ISDN'; $lang['telpcs'] = 'PCS'; $lang['adrintl'] = 'International'; $lang['adrpostal'] = 'Postal'; $lang['adrparcel'] = 'Parcel'; $lang['adrwork'] = 'Work'; $lang['adrdom'] = 'Domestic'; $lang['adrhome'] = 'Home'; $lang['adrpref'] = 'preferred'; +$lang['created_by_davcard'] = 'Created by DAVCard'; +$lang['add_new'] = 'Add new entry'; +$lang['edit'] = 'Edit'; +$lang['js']['confirmation'] = 'Confirmation'; +$lang['js']['yes'] = 'Yes'; +$lang['js']['no'] = 'No'; +$lang['js']['cancel'] = 'Cancel'; +$lang['js']['create'] = 'Create'; +$lang['js']['info'] = 'Info'; +$lang['js']['ok'] = 'OK'; +$lang['js']['edit'] = 'Edit'; +$lang['js']['edit_entry'] = 'Edit Entry'; +$lang['js']['create_entry'] = 'Create Entry'; +$lang['js']['really_delete_this_entry'] = 'Really delete this entry?'; +$lang['js']['firstname'] = 'First Name'; +$lang['js']['lastname'] = 'Last Name'; +$lang['js']['city'] = 'City'; +$lang['js']['zipcode'] = 'Zip Code'; +$lang['js']['cellphone'] = 'Cell Phone'; +$lang['js']['phone'] = 'Phone'; +$lang['js']['street'] = 'Street'; +$lang['js']['country'] = 'Country'; +$lang['js']['email'] = 'Email'; diff --git a/script.js b/script.js new file mode 100644 --- /dev/null +++ b/script.js @@ -0,0 +1,285 @@ +jQuery(function() { + + // Attach to addressbook links + var addressbookpage = jQuery('#davcardAddressbookList').data('addressbookpage'); + if(!addressbookpage) return; + dw_davcard__modals.page = addressbookpage; + + jQuery('div.davcardAddressbookAddNew a').each(function() { + var $link = jQuery(this); + var href = $link.attr('href'); + if (!href) return; + + $link.click( + function(e) { + dw_davcard__modals.showEditContactDialog(null, false); + e.preventDefault(); + return ''; + } + ); + } + ); +}); + +/** + * This holds all modal windows that DAVCal uses. + */ +var dw_davcard__modals = { + $editContactDialog: null, + $confirmDialog: null, + page: null, + uri: null, + action: null, + completeCb: null, + msg: null, + + showEditContactDialog : function(entry, edit) { + if(dw_davcard__modals.$editContactDialog) + return; + + var title = ''; + var dialogButtons = {}; + + if(edit) + { + title = LANG.plugins.davcard['edit_entry']; + dialogButtons[LANG.plugins.davcard['edit']] = function() { + + var postArray = { }; + var pageid = dw_davcard__modals.page; + + jQuery("input.dw_davcard__editcontact").each(function() { + if(jQuery(this).attr('type') == 'checkbox') + { + postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0; + } + else + { + postArray[jQuery(this).prop('name')] = jQuery(this).val(); + } + }); + jQuery('#dw_davcard__ajaxedit').html(''); + jQuery.post( + DOKU_BASE + 'lib/exe/ajax.php', + { + call: 'plugin_davcard', + id: pageid, + page: dw_davcard__modals.page, + action: 'editContact', + params: postArray, + sectok: JSINFO.plugin.davcal['sectok'] + }, + function(data) + { + var result = data['result']; + var html = data['html']; + jQuery('#dw_davcard__ajaxedit').html(html); + if(result === true) + { + dw_davcard__modals.hideEditContactDialog(); + location.reload(); + } + } + ); + }; + dialogButtons[LANG.plugins.davcal['delete']] = function() { + dw_davcard__modals.action = 'deleteContact'; + dw_davcard__modals.msg = LANG.plugins.davcard['really_delete_this_entry']; + dw_davcard__modals.completeCb = function(data) { + var result = data['result']; + if(result === true) + { + dw_davcard__modals.hideEditContactDialog(); + location.reload(); + } + }; + dw_davcard__modals.showDialog(true); + }; + } + else + { + title = LANG.plugins.davcard['create_entry']; + dialogButtons[LANG.plugins.davcard['create']] = function() { + + var postArray = { }; + var pageid = dw_davcard__modals.page; + + jQuery("input.dw_davcard__editcontact").each(function() { + if(jQuery(this).attr('type') == 'checkbox') + { + postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0; + } + else + { + postArray[jQuery(this).prop('name')] = jQuery(this).val(); + } + }); + jQuery('#dw_davcard__ajaxedit').html(''); + jQuery.post( + DOKU_BASE + 'lib/exe/ajax.php', + { + call: 'plugin_davcard', + id: pageid, + page: dw_davcard__modals.page, + action: 'newContact', + params: postArray, + sectok: JSINFO.plugin.davcard['sectok'] + }, + function(data) + { + var result = data['result']; + var html = data['html']; + jQuery('#dw_davcard__ajaxedit').html(html); + if(result === true) + { + dw_davcard__modals.hideEditContactDialog(); + location.reload(); + } + } + ); + }; + } + dialogButtons[LANG.plugins.davcard['cancel']] = function() { + dw_davcard__modals.hideEditContactDialog(); + }; + dw_davcard__modals.$editContactDialog = jQuery(document.createElement('div')) + .dialog({ + autoOpen: false, + draggable: true, + // fix for dragging: http://stackoverflow.com/questions/17247486/jquery-ui-dialog-dragging-issues + drag: function(event, ui) { + var fixPix = jQuery(document).scrollTop(); + iObj = ui.position; + iObj.top = iObj.top - fixPix; + jQuery(this).closest(".ui-dialog").css("top", iObj.top + "px"); + }, + title: title, + resizable: true, + buttons: dialogButtons, + }) + .html( + '
' + + // FIXME: '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + LANG.plugins.davcal['calendar'] + '
' + LANG.plugins.davcard['firstname'] + '
' + LANG.plugins.davcard['lastname'] + '
' + LANG.plugins.davcard['cellphone'] + '
' + LANG.plugins.davcard['phone'] + '
' + LANG.plugins.davcard['email'] + '
' + LANG.plugins.davcard['street'] + '
' + LANG.plugins.davcard['zipcode'] + '
' + LANG.plugins.davcard['city'] + '
' + LANG.plugins.davcard['country'] + '
' + + '' + + '
' + + '
' + ) + .parent() + .attr('id','dw_davcard__edit') + .show() + .appendTo('.dokuwiki:first'); + + jQuery('#dw_davcard__edit').position({ + my: "center", + at: "center", + of: window + }); + + // attach event handlers + jQuery('#dw_davcard__edit .ui-dialog-titlebar-close').click(function(){ + dw_davcard__modals.hideEditContactDialog(); + }); + + + }, + + hideEditContactDialog : function() { + dw_davcard__modals.$editContactDialog.empty(); + dw_davcard__modals.$editContactDialog.remove(); + dw_davcard__modals.$editContactDialog = null; + }, + + hideDialog: function() { + dw_davcard__modals.$dialog.empty(); + dw_davcard__modals.$dialog.remove(); + dw_davcard__modals.$dialog = null; + }, + + showDialog : function(confirm) + { + if(dw_davcard__modals.$confirmDialog) + return; + + var dialogButtons = {}; + var title = ''; + if(confirm) + { + title = LANG.plugins.davcard['confirmation']; + var pageid = dw_davcard__modals.page; + + dialogButtons[LANG.plugins.davcard['yes']] = function() { + jQuery.post( + DOKU_BASE + 'lib/exe/ajax.php', + { + call: 'plugin_davcard', + id: pageid, + page: dw_davcard__modals.page, + action: dw_davcard__modals.action, + params: { + uri: dw_davcard__modals.uri + }, + sectok: JSINFO.plugin.davcard['sectok'] + }, + function(data) + { + dw_davcard__modals.completeCb(data); + } + ); + dw_davcard__modals.hideDialog(); + }; + dialogButtons[LANG.plugins.davcard['cancel']] = function() { + dw_davcard__modals.hideDialog(); + }; + } + else + { + title = LANG.plugins.davcard['info']; + dialogButtons[LANG.plugins.davcard['ok']] = function() { + dw_davcard__modals.hideDialog(); + }; + } + dw_davcard__modals.$dialog = jQuery(document.createElement('div')) + .dialog({ + autoOpen: false, + draggable: true, + //fix for dragging: http://stackoverflow.com/questions/17247486/jquery-ui-dialog-dragging-issues + drag: function(event, ui) { + var fixPix = jQuery(document).scrollTop(); + iObj = ui.position; + iObj.top = iObj.top - fixPix; + jQuery(this).closest(".ui-dialog").css("top", iObj.top + "px"); + }, + title: title, + resizable: true, + buttons: dialogButtons, + }) + .html( + '
' + dw_davcard__modals.msg + '
' + ) + .parent() + .attr('id','dw_davcard__confirm') + .show() + .appendTo('.dokuwiki:first'); + + jQuery('#dw_davcard__confirm').position({ + my: "center", + at: "center", + of: window + }); + // attach event handlers + jQuery('#dw_davcard__confirm .ui-dialog-titlebar-close').click(function(){ + dw_davcard__modals.hideDialog(); + }); + }, + +}; \ No newline at end of file diff --git a/syntax/book.php b/syntax/book.php new file mode 100644 --- /dev/null +++ b/syntax/book.php @@ -0,0 +1,127 @@ + + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); +require_once(DOKU_PLUGIN.'syntax.php'); + +class syntax_plugin_davcard_book extends DokuWiki_Syntax_Plugin { + + protected $hlp = null; + + // Load the helper plugin + public function syntax_plugin_davcard_book() { + $this->hlp =& plugin_load('helper', 'davcard'); + } + + + /** + * What kind of syntax are we? + */ + function getType(){ + return 'substition'; + } + + /** + * What about paragraphs? + */ + function getPType(){ + return 'normal'; + } + + /** + * Where to sort in? + */ + function getSort(){ + return 165; + } + + /** + * Connect pattern to lexer + */ + function connectTo($mode) { + $this->Lexer->addSpecialPattern('\{\{davcardbook>[^}]*\}\}',$mode,'plugin_davcard_book'); + } + + /** + * Handle the match + */ + function handle($match, $state, $pos, Doku_Handler $handler){ + global $ID; + $options = trim(substr($match,14,-2)); + $options = explode(',', $options); + $data = array('name' => $ID, + 'description' => $this->getLang('created_by_davcard'), + 'id' => '', + ); + foreach($options as $option) + { + list($key, $val) = explode('=', $option); + $key = strtolower(trim($key)); + $val = trim($val); + switch($key) + { + case 'id': + if(!in_array($val, $data['id'])) + $data['id'][] = $val; + break; + default: + $data[$key] = $val; + } + } + // Handle the default case when the user didn't enter a different ID + if(empty($data['id'])) + { + $data['id'] = array($ID); + } + // Only update the addressbook name/description if the ID matches the page ID. + // Otherwise, the addressbook is included in another page and we don't want + // to interfere with its data. + if(in_array($ID, $data['id'])) + { + if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) + $username = $_SERVER['REMOTE_USER']; + else + $username = uniqid('davcard-'); + $this->hlp->setAddressbookNameForPage($data['name'], $data['description'], $ID, $username); + } + + $meta = p_get_metadata($ID, 'plugin_davcard'); + if(is_null($meta)) + $meta = array(); + $meta['addressbooks'] = $data; + p_set_metadata($ID, array('plugin_davcard' => $meta)); + } + + /** + * Create output + */ + function render($format, Doku_Renderer $R, $data) + { + global $ID; + if($format !== 'xhtml') + return false; + + // FIXME: Check if the user has write permissions on the page! + // Should we force per-user caching? + + $R->doc .= '
'.$this->getLang('add_new').'
'; + + $R->doc .= '
'; + + $R->doc .= '
'; + + } + + + +} + +// vim:ts=4:sw=4:et:enc=utf-8: diff --git a/syntax/card.php b/syntax/card.php --- a/syntax/card.php +++ b/syntax/card.php @@ -1,164 +1,173 @@ */ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); class syntax_plugin_davcard_card extends DokuWiki_Syntax_Plugin { protected $hlp = null; // Load the helper plugin public function syntax_plugin_davcard_card() { $this->hlp =& plugin_load('helper', 'davcard'); } /** * What kind of syntax are we? */ function getType(){ return 'substition'; } /** * What about paragraphs? */ function getPType(){ return 'normal'; } /** * Where to sort in? */ function getSort(){ return 165; } /** * Connect pattern to lexer */ function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{davcard>[^}]*\}\}',$mode,'plugin_davcard_card'); } /** * Handle the match */ function handle($match, $state, $pos, Doku_Handler $handler){ global $ID; $options = trim(substr($match,10,-2)); $options = explode(',', $options); $data = array('name' => '', 'id' => '', + 'firstname' => '', + 'lastname' => '', ); foreach($options as $option) { list($key, $val) = explode('=', $option); $key = strtolower(trim($key)); $val = trim($val); switch($key) { default: $data[$key] = $val; } } - if($data['id'] === '' && $data['name'] === '') + if($data['id'] === '') { - msg($this->getLang('id_name_not_set'), -1); + if(($data['name'] === '') || (($data['firstname'] === '') && ($data['lastname'] === ''))) + { + msg($this->getLang('id_name_not_set'), -1); + } } return $data; } /** * Create output */ function render($format, Doku_Renderer $R, $data) { if($format == 'metadata') { if(strpos($data['id'], 'webdav://') === 0) { $connectionId = str_replace('webdav://', '', $data['id']); $R->meta['plugin_davcard']['webdavclient'][] = $connectionId; return true; } } if($format != 'xhtml') return false; $contactdata = array(); if(strpos($data['id'], 'webdav://') === 0) { if($data['name'] !== '') { - $contactdata = $this->hlp->getContactByName($data['id'], $data['name']); + $contactdata = $this->hlp->getContactByFormattedName($data['id'], $data['name']); + } + elseif(($data['firstname'] !== '') || ($data['lastname'] !== '')) + { + $contactdata = $this->hlp->getContactByStructuredName($data['id'], $data['firstname'], $data['lastname']); } } $R->doc .= ''.$contactdata['formattedname']; $R->doc .= ''; if(count($contactdata['addr']) > 0) { $R->doc .= ''; foreach($contactdata['addr'] as $type => $addr) { $R->doc .= ''.$this->getLang('adr'.strtolower($type)).''; if($addr[2] != '') { $R->doc .= ''.$addr[2].'
'; } if($addr[5] != '') { $R->doc .= ''.$addr[5].' '; } if($addr[3] != '') { $R->doc .= ''.$addr[3].'
'; } if($addr[6] != '') { $R->doc .= ''.$addr[6].''; } } $R->doc .= '
'; } if(count($contactdata['tel']) > 0) { $R->doc .= ''; foreach($contactdata['tel'] as $type => $number) { $R->doc .= ''.$this->getLang('tel'.strtolower($type)).' '; $R->doc .= $number.'
'; } $R->doc .= '
'; } if(count($contactdata['mail']) > 0) { - $R->doc .= ''; $R->doc .= '
'; } } // vim:ts=4:sw=4:et:enc=utf-8: