1<?php 2/** 3 * DokuWiki Plugin DAVCard (Book Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Andreas Böhler <dev@aboehler.at> 7 */ 8 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11 12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 13require_once(DOKU_PLUGIN.'syntax.php'); 14 15class syntax_plugin_davcard_book extends DokuWiki_Syntax_Plugin { 16 17 protected $hlp = null; 18 19 // Load the helper plugin 20 public function syntax_plugin_davcard_book() { 21 $this->hlp =& plugin_load('helper', 'davcard'); 22 } 23 24 25 /** 26 * What kind of syntax are we? 27 */ 28 function getType(){ 29 return 'substition'; 30 } 31 32 /** 33 * What about paragraphs? 34 */ 35 function getPType(){ 36 return 'normal'; 37 } 38 39 /** 40 * Where to sort in? 41 */ 42 function getSort(){ 43 return 165; 44 } 45 46 /** 47 * Connect pattern to lexer 48 */ 49 function connectTo($mode) { 50 $this->Lexer->addSpecialPattern('\{\{davcardbook>[^}]*\}\}',$mode,'plugin_davcard_book'); 51 } 52 53 /** 54 * Handle the match 55 */ 56 function handle($match, $state, $pos, Doku_Handler $handler){ 57 global $ID; 58 $options = trim(substr($match,14,-2)); 59 $options = explode(',', $options); 60 $data = array('name' => $ID, 61 'description' => $this->getLang('created_by_davcard'), 62 'id' => array(), 63 'filter' => array(), 64 ); 65 foreach($options as $option) 66 { 67 list($key, $val) = explode('=', $option); 68 $key = strtolower(trim($key)); 69 $val = trim($val); 70 switch($key) 71 { 72 case 'filter': 73 list($k, $v) = explode(':', strtolower($val), 2); 74 $data['filter'][$k] = $v; 75 break; 76 case 'id': 77 if(!in_array($val, $data['id'])) 78 $data['id'][] = $val; 79 break; 80 default: 81 $data[$key] = $val; 82 } 83 } 84 // Handle the default case when the user didn't enter a different ID 85 if(empty($data['id'])) 86 { 87 $data['id'] = array($ID); 88 } 89 // Only update the addressbook name/description if the ID matches the page ID. 90 // Otherwise, the addressbook is included in another page and we don't want 91 // to interfere with its data. 92 if(in_array($ID, $data['id'])) 93 { 94 if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER'])) 95 $username = $_SERVER['REMOTE_USER']; 96 else 97 $username = uniqid('davcard-'); 98 $this->hlp->setAddressbookNameForPage($data['name'], $data['description'], $ID, $username); 99 } 100 101 $meta = p_get_metadata($ID, 'plugin_davcard'); 102 if(is_null($meta)) 103 $meta = array(); 104 $meta['addressbooks'] = $data; 105 // Add webdavclient information so that we can disable caching if need be 106 foreach($data['id'] as $addrbkid) 107 { 108 if(strpos($addrbkid, 'webdav://') === 0) 109 { 110 $connectionId = str_replace('webdav://', '', $addrbkid); 111 if(!is_array($meta['webdavclient'])) 112 $meta['webdavclient'] = array(); 113 if(!in_array($addrbkid, $meta['webdavclient'])) 114 $meta['webdavclient'][] = $connectionId; 115 } 116 } 117 p_set_metadata($ID, array('plugin_davcard' => $meta)); 118 return $data; 119 } 120 121 /** 122 * Create output 123 */ 124 function render($format, Doku_Renderer $R, $data) 125 { 126 global $ID; 127 if($format !== 'xhtml') 128 return false; 129 130 $addressbooklist = array(); 131 132 $R->doc .= '<div class="davcardAddressbookAddNew"><a href="#" class="davcardAddressbookAddNew">'.$this->getLang('add_new').'</a></div>'; 133 134 $R->doc .= '<div id="davcardAddressbookList" data-addressbookpage="'.$ID.'">'; 135 $R->doc .= '<table class="davcardAddressbookTable">'; 136 $R->doc .= '<tr><th>'.$this->getLang('name').'</th><th>'.$this->getLang('address').'</th><th>'.$this->getLang('phone').'</th><th>'.$this->getLang('email').'</th></tr>'; 137 foreach($data['id'] as $id) 138 { 139 $write = false; 140 if(strpos($id, 'webdav://') === 0) 141 { 142 $wdc =& plugin_load('helper', 'webdavclient'); 143 if(is_null($wdc)) 144 { 145 echo $this->getLang('no_wdc'); 146 continue; 147 } 148 $connectionId = str_replace('webdav://', '', $id); 149 $settings = $wdc->getConnection($connectionId); 150 if($settings === false) 151 { 152 echo $this->getLang('settings_not_found'); 153 continue; 154 } 155 if($settings['type'] !== 'contacts') 156 { 157 echo $this->getLang('wrong_type'); 158 continue; 159 } 160 $name = $settings['displayname']; 161 $entries = $wdc->getAddressbookEntries($connectionId); 162 $write = $settings['write']; 163 } 164 else 165 { 166 $acl = auth_quickaclcheck($id); 167 if($acl > AUTH_READ) 168 { 169 $write = true; 170 } 171 elseif($acl < AUTH_READ) 172 { 173 continue; 174 } 175 else 176 { 177 $write = false; 178 } 179 $addressbookid = $this->hlp->getAddressbookIdForPage($id); 180 $name = $this->hlp->getAddressBookSettings($addressbookid); 181 $name = $name['displayname']; 182 $entries = $this->hlp->getAddressbookEntries($addressbookid); 183 } 184 185 $addressbooklist[] = array('id' => $id, 'name' => $name, 'write' => $write); 186 187 foreach($entries as $entry) 188 { 189 $contactdata = $this->hlp->parseVcard($entry['contactdata'], $entry['uri'], $write); 190 if(!$this->contactFilterMatch($data['filter'], $contactdata)) 191 continue; 192 $R->doc .= '<tr><td><a href="#" class="plugin_davcard_edit_vcard" data-davcardid="'.$id.'" data-davcarduri="'.hsc($entry['uri']).'" data-write="'.($write ? 'true' : 'false').'">'.hsc($entry['formattedname']).'</a></td><td>'; 193 if(count($contactdata['addr']) > 0) 194 { 195 $R->doc .= '<span class="adr">'; 196 foreach($contactdata['addr'] as $dat) 197 { 198 if(isset($dat['type'])) 199 $type = $dat['type']; 200 else 201 $type = 'other'; 202 $R->doc .= '<span class="type">'.hsc($this->getLang('adr'.strtolower($type))).'</span>'; 203 if($dat['address'][2] != '') 204 { 205 $R->doc .= '<span class="street-address">'.hsc($dat['address'][2]).'</span><br>'; 206 } 207 if($dat['address'][5] != '') 208 { 209 $R->doc .= '<span class="postal-code">'.hsc($dat['address'][5]).' </span>'; 210 } 211 if($dat['address'][3] != '') 212 { 213 $R->doc .= '<span class="locality">'.hsc($dat['address'][3]).'</span><br>'; 214 } 215 216 if($dat['address'][6] != '') 217 { 218 $R->doc .= '<span class="country-name">'.hsc($dat['address'][6]).'</span>'; 219 } 220 } 221 $R->doc .= '</span>'; 222 } 223 $R->doc .= '</td><td>'; 224 if(count($contactdata['tel']) > 0) 225 { 226 $R->doc .= '<span class="tel">'; 227 foreach($contactdata['tel'] as $dat) 228 { 229 if(isset($dat['type'])) 230 $type = $dat['type']; 231 else 232 $type = 'other'; 233 $R->doc .= '<span class="type">'.hsc($this->getLang('tel'.strtolower($type))).' </span>'; 234 $R->doc .= hsc($dat['number']).'<br>'; 235 } 236 $R->doc .= '</span>'; 237 } 238 $R->doc .= '</td><td>'; 239 if(count($contactdata['mail']) > 0) 240 { 241 foreach($contactdata['mail'] as $dat) 242 { 243 $R->doc .= '<span class="email">'.hsc($dat['mail']).'</span><br>'; 244 } 245 } 246 $R->doc .= '</td></tr>'; 247 } 248 } 249 $R->doc .= '</table>'; 250 $R->doc .= '<div id="davcardAddressbookList" class="davcardAddressbookList" style="display:none">'; 251 $R->doc .= '<select id="davcardAddressbookDropdown">'; 252 foreach($addressbooklist as $addrbk) 253 { 254 $R->doc .= '<option value="'.hsc($addrbk['id']).'" data-write="'.hsc($addrbk['write']).'">'.hsc($addrbk['name']).'</option>'; 255 } 256 $R->doc .= '</select></div>'; 257 $R->doc .= '</div>'; 258 259 } 260 261/** 262 * Check if a contact matches a given filter pattern 263 * 264 * @param array $filter The filter array 265 * @param array $contactdata The contact's data to match 266 * 267 * @return true on success, otherwise false 268 */ 269 private function contactFilterMatch($filter, $contactdata) 270 { 271 if(empty($filter)) 272 return true; 273 274 foreach($filter as $type => $params) 275 { 276 $params = '/'.$params.'/i'; 277 switch($type) 278 { 279 case 'name': 280 if(preg_match($params, $contactdata['formattedname']) !== 1) 281 return false; 282 break; 283 case 'mail': 284 $found = false; 285 foreach($contactdata['mail'] as $dat) 286 { 287 if(preg_match($params, $dat['mail']) === 1) 288 $found = true; 289 } 290 if(!$found) 291 return false; 292 break; 293 case 'address': 294 $found = false; 295 foreach($contactdata['addr'] as $dat) 296 { 297 foreach($dat['address'] as $da) 298 { 299 if(preg_match($params, $da) === 1) 300 $found = true; 301 } 302 } 303 if(!$found) 304 return false; 305 break; 306 case 'tel': 307 $found = false; 308 foreach($contactdata['tel'] as $dat) 309 { 310 if(preg_match($params, $dat['number']) === 1) 311 $found = true; 312 } 313 if(!$found) 314 return false; 315 break; 316 } 317 } 318 return true; 319 } 320 321} 322 323// vim:ts=4:sw=4:et:enc=utf-8: 324